주기 V5 (beta)

자동 수집 주기를 봇마다 여러 개 만들고 고칩니다.

주기는 이름 + 언제 + 조건 + 입력 방식 + 결과 저장(유니온)입니다. 한 봇에 여러 개 둘 수 있고, 주기마다 자기 조건으로 돕니다. 화면의 주기 목록과 같은 자원입니다. 주기가 도는 결과는 주기 실행 결과, 돌고 난 데이터는 데이터셋에서 봅니다.

엔드포인트

  • GET /v5/api/bots/{bot_id}/plans 주기 목록
  • POST /v5/api/bots/{bot_id}/plans 주기 만들기(재시도 키 필수)
  • GET /v5/api/plans/{plan_id} 주기 하나
  • PATCH /v5/api/plans/{plan_id} 보낸 것만 고치기
  • DELETE /v5/api/plans/{plan_id} 주기 지우기(데이터셋은 남음)
  • POST /v5/api/plans/{plan_id}/copy_settings 봇 설정 값 불러오기
  • POST /v5/api/plans/{plan_id}/preview 저장 없이 미리보기
  • PUT /v5/api/plans/{plan_id}/excel 주기 전용 엑셀(아직 지원하지 않음)

주기 id 와 열려 있는 계정

주기 id 는 글자입니다. 주기 모드로 만든 주기는 "512" 같은 숫자 글자, 아직 주기 행이 없는 기존 봇의 계산된 주기 1은 "one-<봇 ID>"(예: one-8f3a7c1e9b5d24f6)입니다. 이름·조건·끄기를 고치면 그 봇이 주기 모드로 바뀌며 주기 행이 생기므로, 응답의 id를 확인해 이후에 쓰세요.

여러 주기 기능이 열려 있지 않은 계정은 이 쪽의 모든 경로(그리고 run·runs·데이터셋의 plan_id 거르기)가 404 PLAN_NOT_FOUND입니다.

조회

목록은 켜진 순서가 아니라 화면 순서(주기 1이 맨 앞)입니다. 주기 1은 linked: true로 봇 설정을 따라갑니다 — 조건을 따로 정하면 연결이 풀립니다.

칸설명
id주기 id(글자).
name주기 이름. 만들 때 안 주면 "주기 N".
enabled켜져 있는지.
linkedtrue면 봇 설정을 따라갑니다.
when언제 도는지 — 아래 5가지 유형.
label·label_enwhen을 읽기 좋게 쓴 문장(한국어·영어).
inputs이 주기가 쓰는 조건 { param1: 값 }. 봇 설정을 따라가면 봇 설정 값.
conditions조건을 한 줄로 줄인 목록 [{ name, value }].
input_modedirect 또는 excel.
union{ enabled, target_dataset_id }.
next_runs다음 수집 시각 5개(켜져 있을 때).
요청 예시
curl 'https://www.hashscraper.com/v5/api/bots/8f3a7c1e9b5d24f6/plans' \
  -H 'Authorization: Bearer YOUR_API_KEY'
응답 예시 200
{
  "result": "success",
  "version": "v5",
  "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21",
  "elapsed_sec": 0.0123,
  "count": 2,
  "data": {
    "bot_id": "8f3a7c1e9b5d24f6",
    "plans": [
      {
        "id": "one-8f3a7c1e9b5d24f6",
        "bot_id": "8f3a7c1e9b5d24f6",
        "name": "주기 1",
        "enabled": true,
        "linked": true,
        "when": {
          "type": "daily",
          "times": [
            "09:00"
          ]
        },
        "label": "매일 09:00 (KST)",
        "label_en": "Every day at 09:00 (KST)",
        "inputs": {
          "param1": "sneakers"
        },
        "conditions": [
          {
            "name": "Keyword",
            "value": "sneakers"
          }
        ],
        "input_mode": "direct",
        "union": {
          "enabled": false,
          "target_dataset_id": null
        },
        "next_runs": [
          "2026-10-05T09:00:00+09:00",
          "2026-10-06T09:00:00+09:00"
        ]
      },
      {
        "id": "512",
        "bot_id": "8f3a7c1e9b5d24f6",
        "name": "주기 2",
        "enabled": true,
        "linked": false,
        "when": {
          "type": "weekly",
          "every_weeks": 1,
          "anchor": null,
          "days": [
            "mon"
          ],
          "times": [
            "09:00"
          ]
        },
        "label": "매주 월요일 09:00 (KST)",
        "label_en": "Every Monday at 09:00 (KST)",
        "inputs": {
          "param1": "sneakers"
        },
        "conditions": [
          {
            "name": "Keyword",
            "value": "sneakers"
          }
        ],
        "input_mode": "direct",
        "union": {
          "enabled": false,
          "target_dataset_id": null
        },
        "next_runs": [
          "2026-10-05T09:00:00+09:00",
          "2026-10-12T09:00:00+09:00",
          "2026-10-19T09:00:00+09:00"
        ]
      }
    ]
  }
}
요청 예시
curl 'https://www.hashscraper.com/v5/api/plans/512' \
  -H 'Authorization: Bearer YOUR_API_KEY'
응답 예시 200
{
  "result": "success",
  "version": "v5",
  "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21",
  "elapsed_sec": 0.0123,
  "data": {
    "id": "512",
    "bot_id": "8f3a7c1e9b5d24f6",
    "name": "주기 2",
    "enabled": true,
    "linked": false,
    "when": {
      "type": "weekly",
      "every_weeks": 1,
      "anchor": null,
      "days": [
        "mon"
      ],
      "times": [
        "09:00"
      ]
    },
    "label": "매주 월요일 09:00 (KST)",
    "label_en": "Every Monday at 09:00 (KST)",
    "inputs": {
      "param1": "sneakers"
    },
    "conditions": [
      {
        "name": "Keyword",
        "value": "sneakers"
      }
    ],
    "input_mode": "direct",
    "union": {
      "enabled": false,
      "target_dataset_id": null
    },
    "next_runs": [
      "2026-10-05T09:00:00+09:00",
      "2026-10-12T09:00:00+09:00",
      "2026-10-19T09:00:00+09:00"
    ]
  }
}

언제 돌지 — when 유형 5가지

when은 식이 아니라 화면 값 그대로 보냅니다. 시각은 "HH:MM"(24시간, KST)이며 여러 개를 줄 수 있습니다.

manual·custom은 주기에 쓸 수 없습니다. 주기를 멈추려면 enabled: false로 끄세요. 값이 맞지 않으면 400 INVALID_PARAM이고 details.errors에 이유가 있습니다. 화면으로 표현할 수 없는 옛 식은 { "type": "custom", "editable": false }로 읽히며 이 경로로는 바꿀 수 없습니다.

type칸뜻
intervalminutesN분마다.
dailytimes매일 정해진 시각.
daysevery_days(2 이상)·anchor(기준일)·timesN일마다. 기준일부터 N일 간격.
weeklyevery_weeks(기본 1)·anchor·days(mon~sun)·timesN주마다 정해진 요일. every_weeks가 2 이상이면 anchor가 기준 주를 정합니다(없으면 이번 주).
monthlydates(1~31과 "last")·times매월 정해진 날짜.
when · interval
{
  "type": "interval",
  "minutes": 10
}
when · daily
{
  "type": "daily",
  "times": [
    "09:00",
    "18:30"
  ]
}
when · days
{
  "type": "days",
  "every_days": 3,
  "anchor": "2026-10-05",
  "times": [
    "09:00"
  ]
}
when · weekly
{
  "type": "weekly",
  "every_weeks": 2,
  "anchor": "2026-10-05",
  "days": [
    "mon",
    "thu"
  ],
  "times": [
    "09:00"
  ]
}
when · monthly
{
  "type": "monthly",
  "dates": [
    1,
    15,
    "last"
  ],
  "times": [
    "06:00"
  ]
}

만들기

본문: when(필수), name(없으면 "주기 N"), inputs(없으면 지금 봇 설정 값으로 채움), union(true·false 또는 { enabled }), enabled(기본 true). 만든 주기는 주기 2부터와 같이 처음부터 자기 조건을 가집니다. 성공하면 201과 주기를 돌려줍니다.

재시도 중복 방지 키가 필수입니다(없으면 400 IDEMPOTENCY_KEY_REQUIRED). 같은 키로 다시 보내면 주기가 둘 생기지 않고 첫 응답을 돌려줍니다.

요청 예시
curl -X POST 'https://www.hashscraper.com/v5/api/bots/8f3a7c1e9b5d24f6/plans' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H "Idempotency-Key: $(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Monday morning",
  "when": {
    "type": "weekly",
    "days": [
      "mon"
    ],
    "times": [
      "09:00"
    ]
  },
  "inputs": {
    "param1": "sneakers"
  }
}'
응답 예시 201
{
  "result": "success",
  "version": "v5",
  "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21",
  "elapsed_sec": 0.0123,
  "data": {
    "id": "512",
    "bot_id": "8f3a7c1e9b5d24f6",
    "name": "Monday morning",
    "enabled": true,
    "linked": false,
    "when": {
      "type": "weekly",
      "every_weeks": 1,
      "anchor": null,
      "days": [
        "mon"
      ],
      "times": [
        "09:00"
      ]
    },
    "label": "매주 월요일 09:00 (KST)",
    "label_en": "Every Monday at 09:00 (KST)",
    "inputs": {
      "param1": "sneakers"
    },
    "conditions": [
      {
        "name": "Keyword",
        "value": "sneakers"
      }
    ],
    "input_mode": "direct",
    "union": {
      "enabled": false,
      "target_dataset_id": null
    },
    "next_runs": [
      "2026-10-05T09:00:00+09:00",
      "2026-10-12T09:00:00+09:00",
      "2026-10-19T09:00:00+09:00"
    ]
  }
}

고치기

name·enabled·when·inputs·union·input_mode 중 보낸 것만 바뀝니다(하나도 없으면 MISSING_PARAM). input_mode는 direct만 받습니다. union.target_dataset_id는 이 주기가 만든 데이터셋이어야 합니다. 봇 설정을 따라가는 주기에 inputs·union을 보내면 연결이 풀리고 자기 조건을 가집니다.

요청 예시
curl -X PATCH 'https://www.hashscraper.com/v5/api/plans/512' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H "Idempotency-Key: $(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{
  "enabled": false
}'
요청 예시
curl -X PATCH 'https://www.hashscraper.com/v5/api/plans/512' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H "Idempotency-Key: $(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{
  "when": {
    "type": "daily",
    "times": [
      "07:30"
    ]
  },
  "inputs": {
    "param1": "boots"
  }
}'

지우기

주기를 지워도 그 주기가 만든 데이터셋은 남습니다. 주기 1(봇 설정을 따라가는 주기·계산된 주기 1)은 지울 수 없고 409 PLAN_UNDELETABLE입니다. 끄려면 PATCH로 enabled: false를 보내세요.

요청 예시
curl -X DELETE 'https://www.hashscraper.com/v5/api/plans/512' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H "Idempotency-Key: $(uuidgen)"
응답 예시 200
{
  "result": "success",
  "version": "v5",
  "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21",
  "elapsed_sec": 0.0123,
  "data": {
    "id": "512",
    "deleted": true
  }
}

봇 설정 값 불러오기

화면의 "주기에도 맞추기"입니다. 봇 설정의 지금 값을 따로 정한 주기에 복사합니다. fields에 칸 이름(name·name_en) 또는 paramN 배열을 주면 그 칸만, 안 주면 봇이 쓰는 칸 전부입니다. 응답의 copied_fields가 실제로 복사한 칸입니다. 봇 설정을 따라가는 주기는 이미 같은 값을 읽으므로 바뀌는 것이 없습니다([]).

요청 예시
curl -X POST 'https://www.hashscraper.com/v5/api/plans/512/copy_settings' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H "Idempotency-Key: $(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{
  "fields": [
    "Keyword"
  ]
}'
응답 예시 200
{
  "result": "success",
  "version": "v5",
  "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21",
  "elapsed_sec": 0.0123,
  "data": {
    "id": "512",
    "bot_id": "8f3a7c1e9b5d24f6",
    "name": "주기 2",
    "enabled": true,
    "linked": false,
    "when": {
      "type": "weekly",
      "every_weeks": 1,
      "anchor": null,
      "days": [
        "mon"
      ],
      "times": [
        "09:00"
      ]
    },
    "label": "매주 월요일 09:00 (KST)",
    "label_en": "Every Monday at 09:00 (KST)",
    "inputs": {
      "param1": "sneakers"
    },
    "conditions": [
      {
        "name": "Keyword",
        "value": "sneakers"
      }
    ],
    "input_mode": "direct",
    "union": {
      "enabled": false,
      "target_dataset_id": null
    },
    "next_runs": [
      "2026-10-05T09:00:00+09:00",
      "2026-10-12T09:00:00+09:00",
      "2026-10-19T09:00:00+09:00"
    ],
    "copied_fields": [
      "param1"
    ]
  }
}

미리보기

저장하지 않고 when이 어떻게 도는지 봅니다. 본문의 when이 없으면 그 주기의 지금 값을 씁니다. count(1~20, 기본 5)만큼의 다음 수집 시각과 문장(한국어·영어), 한 달 평균 횟수 runs_per_month를 돌려줍니다. 예상 크레딧은 주지 않습니다.

요청 예시
curl -X POST 'https://www.hashscraper.com/v5/api/plans/512/preview' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H "Idempotency-Key: $(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{
  "when": {
    "type": "monthly",
    "dates": [
      1,
      15
    ],
    "times": [
      "06:00"
    ]
  },
  "count": 3
}'
응답 예시 200
{
  "result": "success",
  "version": "v5",
  "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21",
  "elapsed_sec": 0.0123,
  "data": {
    "id": "512",
    "when": {
      "type": "monthly",
      "dates": [
        1,
        15
      ],
      "times": [
        "06:00"
      ]
    },
    "label": "매월 1일, 15일 06:00 (KST)",
    "label_en": "Monthly on the 1st and 15th at 06:00 (KST)",
    "sentence": {
      "ko": "매월 1일, 15일 06:00 (KST)에 수집합니다.",
      "en": "Collects monthly on the 1st and 15th at 06:00 (KST)."
    },
    "next_runs": [
      "2026-10-15T06:00:00+09:00",
      "2026-11-01T06:00:00+09:00",
      "2026-11-15T06:00:00+09:00"
    ],
    "runs_per_month": 2
  }
}

주기 전용 엑셀

주기가 엑셀로 도는 기능은 v5 1차 범위 밖입니다. 이 경로는 주소만 있고 항상 422 EXCEL_NOT_SUPPORTED_YET입니다.

요청 예시
curl -X PUT 'https://www.hashscraper.com/v5/api/plans/512/excel' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H "Idempotency-Key: $(uuidgen)" \
  -F 'file=@products.xlsx'
응답 예시 422
{
  "result": "error",
  "version": "v5",
  "request_id": "req_5a8c1f1c-9b2d-4e7c-9abf-3f7e0a4d1b21",
  "code": "EXCEL_NOT_SUPPORTED_YET",
  "message": "Collecting with Excel input is not supported in v5 yet.",
  "elapsed_sec": 0.0011
}

쓰기에서 만나는 오류

코드HTTP뜻
PLAN_CONDITION_BLOCKED422이 봇은 주기마다 따로 조건을 둘 수 없습니다.
PLAN_NAME_TAKEN422같은 이름의 주기가 이미 있습니다.
PLAN_UNDELETABLE409주기 1은 지울 수 없습니다.
PLAN_MODE_REFUSED422이 봇은 주기 모드로 바꿀 수 없습니다(details.reason에 이유, 옛 방식이 도는 중이면 legacy_running).
EXCEL_NOT_SUPPORTED_YET422엑셀 입력은 아직 지원하지 않습니다.
FORBIDDEN403체험 계정의 봇은 바꿀 수 없습니다.
INVALID_PARAM400값이 맞지 않습니다. details.errors를 보세요.

함께 보면 좋은 가이드