課金スケジュールの一括作成
CSVファイルをアップロードして、単一の操作で複数の課金スケジュールを作成します。このエンドポイントは非同期の一括作成ジョブを開始し、進捗の監視やステータスレポートのダウンロードに使用できるrecurring_idを返します。
API認証情報
リクエストパラメータ
必須 - 1フィールド必須パラメータ
`file`FILE(required)
課金スケジュールデータを含むCSVファイル。各行は作成する1つのスケジュールを表します。
CSV構造CSVカラム
`customer_key`STRING(required)
ステータスレポートでこの行を追跡するための一意の識別子。システムにとって意味のある任意の文字列を使用できます。
`customer`STRING(required)
課金される顧客ID(cust_*)。顧客には少なくとも1枚のカードが紐付けられている必要があります。
`card`STRING(optional)
課金する特定のカードID。指定しない場合、顧客のデフォルトカードが使用されます。
`amount`INTEGER(required)
最小通貨単位での課金額(例:THBの場合はサタン、USDの場合はセント)。
`description`STRING(optional)
このスケジュールによって作成される各課金に表示される説明。
`every`INTEGER(required)
頻度の乗数。例えば、every=2でperiod=monthの場合、2ヶ月ごとを意味します。
`period`STRING(required)
スケジュール頻度の時間単位。
`days_of_month`STRING(optional)
月次スケジュールの場合:課金する特定の日(1-28)。複数の日を指定するにはセミコロンを使用。
`start_date`STRING(optional)
YYYY-MM-DD形式のスケジュール開始日。指定しない場合は今日がデフォルト。
`end_date`STRING(optional)
YYYY-MM-DD形式のスケジュール終了日。この日以降、スケジュールは期限切れになります。
レスポンス
200
アップロード受理CSVファイルが受理され、一括作成ジョブがキューに入りました。返されたrecurring_idを使用して進捗を監視してください。
レスポンスに含まれる内容:
object- 常に "recurring_export"id- ジョブ追跡用のRecurring export ID (recr_*)livemode- 本番モードの操作かどうかlocation- ジョブを監視するためのAPIパスstate- 初期状態(通常 "pending")total_rows- CSVで検出された行数processed_rows- 処理済みの行数(初期は0)successful_rows- 作成成功数(初期は0)failed_rows- 作成失敗数(初期は0)created_at- ジョブ作成タイムスタンプ
400
不正なリクエストリクエストの検証に失敗しました。詳細はエラーメッセージを確認してください。
一般的な原因:
- ファイルが存在しないか空
- 無効なCSV形式または構造
- CSVヘッダーに必須カラムがない
- ファイルが10MBの制限を超過
- CSVが10,000行を超過
401
認証エラー認証に失敗しました。APIキーが無効または欠落しています。
一般的な原因:
- Authorizationヘッダーが欠落
- 無効なシークレットキー
- シークレットキーの代わりにパブリックキーを使用
- HTTP Basic Auth形式が不正
404
見つかりませんエンドポイントが見つからないか、機能が有効になっていません。
一般的な原因:
- アカウントで一括操作機能が有効になっていない
- APIエンドポイントURLが不正
5xx
サーバーエラーサーバー側でエラーが発生しました。これらは稀ですが、適切に処理する必要があります。
対処方法:
- 指数バックオフでリクエストをリトライ
- status.omise.coでサービスインシデントを確認
- 詳細なガイダンスはエラー処理を参照
コードサンプル
- cURL
- Ruby
- Python
- Node.js
- PHP
- Java
- C#
- Go
# CSVファイルをアップロードして複数の課金スケジュールを作成
curl https://api.omise.co/schedules/upload \
-X POST \
-u skey_test_5xuy4w91xqz7d1w9u0t: \
-F "file=@/path/to/schedules.csv"
require 'omise'
require 'net/http'
require 'uri'
Omise.api_key = 'skey_test_5xuy4w91xqz7d1w9u0t'
uri = URI('https://api.omise.co/schedules/upload')
request = Net::HTTP::Post.new(uri)
request.basic_auth(Omise.api_key, '')
form_data = [['file', File.open('/path/to/schedules.csv')]]
request.set_form(form_data, 'multipart/form-data')
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
result = JSON.parse(response.body)
puts "Job ID: #{result['id']}"
import omise
import requests
omise.api_secret = 'skey_test_5xuy4w91xqz7d1w9u0t'
with open('/path/to/schedules.csv', 'rb') as csv_file:
response = requests.post(
'https://api.omise.co/schedules/upload',
auth=(omise.api_secret, ''),
files={'file': csv_file}
)
result = response.json()
print(f"Job ID: {result['id']}")
print(f"Total rows: {result['total_rows']}")
const omise = require('omise')({
secretKey: 'skey_test_5xuy4w91xqz7d1w9u0t'
});
const fs = require('fs');
const FormData = require('form-data');
const axios = require('axios');
const form = new FormData();
form.append('file', fs.createReadStream('/path/to/schedules.csv'));
const response = await axios.post('https://api.omise.co/schedules/upload', form, {
auth: {
username: 'skey_test_5xuy4w91xqz7d1w9u0t',
password: ''
},
headers: form.getHeaders()
});
console.log('Job ID:', response.data.id);
console.log('Total rows:', response.data.total_rows);
<?php
define('OMISE_SECRET_KEY', 'skey_test_5xuy4w91xqz7d1w9u0t');
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => 'https://api.omise.co/schedules/upload',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_USERPWD => OMISE_SECRET_KEY . ':',
CURLOPT_POSTFIELDS => [
'file' => new CURLFile('/path/to/schedules.csv', 'text/csv', 'schedules.csv')
]
]);
$response = curl_exec($curl);
curl_close($curl);
$result = json_decode($response, true);
echo "Job ID: " . $result['id'] . "\n";
echo "Total rows: " . $result['total_rows'] . "\n";
import java.io.File;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.util.Base64;
HttpClient client = HttpClient.newHttpClient();
String boundary = "----WebKitFormBoundary" + System.currentTimeMillis();
File csvFile = new File("/path/to/schedules.csv");
byte[] fileBytes = Files.readAllBytes(csvFile.toPath());
String body = "--" + boundary + "\r\n" +
"Content-Disposition: form-data; name=\"file\"; filename=\"schedules.csv\"\r\n" +
"Content-Type: text/csv\r\n\r\n" +
new String(fileBytes) + "\r\n" +
"--" + boundary + "--";
String auth = Base64.getEncoder().encodeToString("skey_test_5xuy4w91xqz7d1w9u0t:".getBytes());
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.omise.co/schedules/upload"))
.header("Authorization", "Basic " + auth)
.header("Content-Type", "multipart/form-data; boundary=" + boundary)
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
using System.Net.Http;
using System.Net.Http.Headers;
var client = new HttpClient();
var credentials = Convert.ToBase64String(
System.Text.Encoding.ASCII.GetBytes("skey_test_5xuy4w91xqz7d1w9u0t:")
);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic", credentials);
using var content = new MultipartFormDataContent();
using var fileStream = File.OpenRead("/path/to/schedules.csv");
var fileContent = new StreamContent(fileStream);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
content.Add(fileContent, "file", "schedules.csv");
var response = await client.PostAsync("https://api.omise.co/schedules/upload", content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
func main() {
file, _ := os.Open("/path/to/schedules.csv")
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("file", "schedules.csv")
io.Copy(part, file)
writer.Close()
req, _ := http.NewRequest("POST", "https://api.omise.co/schedules/upload", body)
req.SetBasicAuth("skey_test_5xuy4w91xqz7d1w9u0t", "")
req.Header.Set("Content-Type", writer.FormDataContentType())
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Printf("Job ID: %s\n", result["id"])
}
CSVファイルの例
customer_key,customer,card,amount,description,every,period,days_of_month,start_date,end_date
sub_001,cust_test_5xuy4w91xqz7d1w9u0t,,100000,Monthly premium plan,1,month,1,2025-02-01,2026-01-31
sub_002,cust_test_5xuy4w91xqz7d1w9u0t,card_test_5xuy4w91xqz7d1w9u0t,50000,Basic subscription,1,month,15,2025-02-01,
sub_003,cust_test_5xuy4w91xqz7d1w9u0t,,200000,Enterprise plan,1,month,1;15,2025-02-01,2025-12-31
エラーと結果コード
一般的なエラーコード
| コード | 説明 | 解決方法 |
|---|---|---|
authentication_failure | 無効なAPIキー | シークレットキーが正しいことを確認 |
invalid_file | ファイルが欠落または無効 | ファイルが有効なCSVであることを確認 |
file_too_large | ファイルが10MB制限を超過 | より小さいファイルに分割 |
invalid_csv_structure | 必須カラムが欠落 | CSVヘッダー行を確認 |
too_many_rows | CSVが10,000行を超過 | 複数のファイルに分割 |
CSV行エラーコード
| コード | 説明 | 解決方法 |
|---|---|---|
invalid_customer | 顧客IDが見つかりません | 顧客が存在することを確認 |
no_card_attached | 顧客にカードがない | まず顧客にカードを紐付け |
invalid_card | カードIDが見つからないか期限切れ | 有効なカードIDを使用 |
invalid_amount | 金額が無効 | 正の整数を使用 |
invalid_period | 期間の値が無効 | day、week、またはmonthを使用 |
invalid_date_format | 日付形式が無効 | YYYY-MM-DD形式を使用 |