回補歷史資料

按頁讀取觀測值端點,直到游標為空:2025 年 11 月 3 日至 2026 年 10 月 23 日的 USD/IDR 每日匯率共 249 天,按每頁 100 列計算只需 3 次請求。每個帳戶都可以回溯到該資料序列的起點。

用 API 回補

觀測值端點接受日期範圍、頁大小上限和游標。外匯匯率使用 /v1/fx/rates/{base}/observations,CPI 使用 /v1/economics/{country}/cpi/observations,大宗商品 K 線使用 /v1/commodities/spot/{commodity}/{currency}/bars。日期參數依端點不同,為 start 和 end,或 start_date 和 end_date。每個回應都有 next_cursor,最後一頁該值為 null。

  1. 設定你的 API 金鑰 取得免費 API 金鑰,並將它存放在環境變數 NARWHAL_API_KEY 中。指令碼會讀取該變數,並以 Authorization: Bearer YOUR_KEY 將金鑰傳送至 https://api.narwhalapi.com。
  2. 設定資料序列和日期範圍 範例請求 2025 年 11 月 1 日至 2026 年 10 月 23 日的 USD/IDR,limit 設為 100。傳送上一個回應回傳的游標時,每一頁都要保持相同的篩選條件。
  3. 把每一頁儲存到檔案 使用該腳本把每筆觀測值作為一行 JSON 附加到 usd_idr.jsonl。只要 next_cursor 有值就繼續傳送請求,該值為空時停止。
    Python:把一年的 USD/IDR 每日匯率儲存到檔案
    import json, os
    import requests
    
    H = {"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"}
    params = {
        "currencies": "IDR",
        "start_date": "2025-11-01",
        "end_date": "2026-10-23",
        "limit": 100,
    }
    rows, pages, cursor = 0, 0, None
    with open("usd_idr.jsonl", "a") as out:
        while True:
            if cursor:
                params["cursor"] = (
                    cursor  # the cursor carries the filters; resend them unchanged
                )
            r = requests.get(
                "https://api.narwhalapi.com/v1/fx/rates/USD/observations",
                params=params,
                headers=H,
                timeout=15,
            )
            r.raise_for_status()
            body = r.json()
            for day in body["observations"]:
                out.write(json.dumps(day) + "\n")
                rows += 1
            pages += 1
            cursor = body.get("next_cursor")
            if not cursor:
                break
    print(pages, "pages,", rows, "days")
  4. 查看回傳的日期 對於 2025 年 11 月 1 日至 2026 年 10 月 23 日的範圍,腳本會輸出 3 pages, 249 days。回應的起始日期可能晚於你請求的起始日期,所以除了最後一個日期,也要查看第一個已儲存的日期。

腳本分別統計頁數和天數。它先寫入每筆觀測值,再請求下一頁,游標迴圈結束後輸出合計。檔案以附加模式開啟,每一行儲存一筆觀測值。請求讀取的是以 USD 為基礎貨幣的 IDR 資料序列。

每一頁按一次呼叫從你的額度中扣除,使用免費額度的帳戶每分鐘限 50 次請求。回補多個資料序列時,即使每個序列只需要幾頁,也需要在頁與頁之間留出間隔,才能不超過每分鐘的限制。

回應帶有 X-RateLimit-Remaining。如果某頁請求回傳 429 rate_limit_exceeded,請先依 Retry-After 的值等待,再請求下一頁。402 insufficient_credits 回應表示餘額已用完,請先儲值再繼續。錯誤使用 application/problem+json,並包含 status、code、detail 和 request_id,因此要根據錯誤代碼判斷回補能否繼續。

使用試算表或無程式碼工作流程

幾百列的資料用 Sheets 匯入就足夠了。對於一次性的回補,腳本比迴圈翻頁的工作流程更簡單。如果希望觀測值一到就寫入,請使用檔案方式;Python 範例在整個回補過程中都會附加資料列。

n8n、Make 或 Zapier 也可以用游標迴圈翻頁。工作流程每次傳送游標時都要帶上相同的日期和資料序列篩選條件,並在 next_cursor 為 null 時停止。持續更新的資料流可以先做一次回補,再接上每日資料拉取。

選擇回補方式

情況最適合的方式原因
一次性回補單一資料序列一年的資料腳本它逐頁讀取整個範圍,並把資料列附加到檔案
多個資料序列遍歷各資料序列,並在頁與頁之間暫停暫停可使請求保持在每分鐘限制之內
持續更新的資料流先回補一次,再每天拉取回補會補上每日拉取開始之前的歷史資料

回補中途停止了怎麼辦?

從上次儲存的日期重新開始。腳本每收到觀測值就附加 JSON 行,所以即使工作中斷,已寫入的資料列仍保留在檔案中。把這個已儲存的日期作為繼續該範圍的起點。

儲存的游標可能會過期。如果請求回傳 409 cursor_expired,請不帶游標重新開始,並從上次儲存的日期繼續。游標攜帶了其範圍的篩選條件,所以在翻頁讀取該範圍期間,不要更改這些條件。

每頁最多可以請求多少列?

limit 最大可設為該端點的上限:外匯匯率觀測值為 366,經濟資料觀測值為 1,000,大宗商品 K 線為 500,經濟日曆為 100。預設值為 100。limit 只控制頁大小,你仍然需要沿著 next_cursor 一直讀取,直到回應中沒有下一頁。

為什麼我的回補比請求的起始日期晚開始?

所有帳戶都可讀取完整歷史。回傳的第一個日期顯示序列實際從何時開始,因此請求更早的開始日期並不保證回傳更早的列。

計算範例:2025 年 11 月 1 日至 2026 年 10 月 23 日的 USD/IDR

以 2025 年 11 月 1 日為起始、2026 年 10 月 23 日為結束、頁大小上限 100 來請求 USD/IDR,並用相同的篩選條件依序使用回傳的游標。在這個範圍內,回應共有 3 頁 249 列,所以回補需要 3 次請求。

第一列是 2025 年 11 月 3 日星期一,因為 2025 年 11 月 1 日和 2 日是週末。2025 年 11 月 3 日的 USD/IDR 匯率為 16,710.3,2026 年 10 月 23 日為 18,107.8。

項目結果
請求的範圍2025 年 11 月 1 日至 2026 年 10 月 23 日
頁大小上限100 列
該範圍的頁數和請求數3 頁,3 次請求
該範圍的列數249
第一筆觀測值2025 年 11 月 3 日:每 1 USD 兌 16,710.3 IDR
最後一筆觀測值2026 年 10 月 23 日:每 1 USD 兌 18,107.8 IDR

發布於 。

後續步驟