OriUta のAPIは、プログラムからオリジナルソングを作ります。入力はお祝いの場面といくつかの具体的な情報、出力は完成した歌詞と制作済みの音源です。HTTPSとJSONだけで動き、必須のSDKはありません。
最終更新: 2026-09-16
キーは手作業で発行しています。ご計画、想定件数、対応言語を短くお知らせいただければ十分で、通常は一営業日で開通します。
APIはウェブサイトとまったく同じことをします。場面、歌う相手の名前、そしていくつかの具体的な情報を送ってください。そこからまず完成した歌詞ができ、続いてボーカル、アレンジ、ミックスを含む音源が制作されます。全体で通常は5分から10分です。
すべてのリクエストは https://api.oriuta.jp/v1 に送ります。APIはHTTPSのみを受け付け、JSONを受け取りJSONで返します。必須のSDKはなく、HTTPを話せる言語であれば何でも構いません。このページの例ではcurl、Python、Nodeを使っています。この三つが最も多いためです。
ドメインごとにAPIのベースURLと現地通貨での価格があります。キーは発行されたドメインで有効です。複数の市場を扱う場合は、複数のキーを受け取るか、複数ドメインに開放された一つのキーを受け取ります。
課金は完成した曲に対して行われ、現在は ¥2980 です。下書き、キャンセルされた依頼、再生成には費用がかかりません。
自動登録はあえて用意していません。1曲ごとに実際の制作コストがかかるため、またその連携が何に使われるのかを把握したいため、キーは手作業で発行しています。実際には短いメールと一営業日だけの話です。
songs@maxkuch.com 宛に、次の四点をお知らせください。
キーは二つお渡しします。接頭辞 sk_test_ のテストキーは無料で、固定のデモ音源を返します。接頭辞 sk_live_ の本番キーが本番用です。どちらもすぐに使え、エンドポイントごとの個別開放は必要ありません。
すべてのリクエストは、Authorizationヘッダーにベアラートークンとしてキーを載せます。有効なヘッダーがないリクエストは401とエラー種別 authentication_error を返します。
curl https://api.oriuta.jp/v1/songs \
-H "Authorization: Bearer $SONG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"occasion": "birthday",
"recipient_name": "Anna",
"relationship": "sister",
"language": "ja",
"mood": "happy",
"style": "pop",
"voice": "female",
"details": "Climbs every weekend, always ten minutes late, calls everyone chef.",
"callback_url": "https://example.com/hooks/songs"
}'
キーはパスワードと同じ扱いにしてください。サーバー側だけで使い、フロントエンドのコードや公開リポジトリには絶対に置かないでください。漏れた場合はご連絡いただければ即座に無効化し、新しいキーを発行します。アカウントは複数の有効なキーを持てるので、切り替えは無停止で行えます。
テストキーと本番キーは同じエンドポイントを使います。リクエストがテストモードで処理されたかどうかは、各オブジェクトの livemode フィールドでわかります。
曲の作成は一回の呼び出しです。レスポンスはすぐに返り、ステータス queued のIDが入っています。残りはすべてバックグラウンドで進みます。
import os, time, requests
API = "https://api.oriuta.jp/v1"
HEAD = {"Authorization": "Bearer " + os.environ["SONG_API_KEY"]}
song = requests.post(API + "/songs", headers=HEAD, json={
"occasion": "wedding",
"recipient_name": "Lea and Tim",
"relationship": "friends",
"language": "ja",
"mood": "romantic",
"details": "Met at a bike repair shop, dog named Miso, both terrible dancers.",
}).json()
while song["status"] not in ("preview_ready", "complete", "failed"):
time.sleep(5)
song = requests.get(API + "/songs/" + song["id"], headers=HEAD).json()
print(song["lyrics"])
print(song["preview_url"])
例はわかりやすさのために5秒ごとに問い合わせています。本番ではWebhookのほうが適しています。接続を開いたままにする必要も、待ち続ける必要もなくなるためです。どちらの方式にも対応しており、Webhookについては後述します。
決め手になるのは details フィールドです。ここにその人の具体的な話を入れます。あだ名、こだわり、うまくいかなかった旅行など。「優しい人です」のような一般的な文からは一般的な歌詞しか生まれません。具体的な情報が三つから五つあれば十分で、それが「ただ感じのよい曲」と「その人についての曲」を分けます。
| メソッド | パス | 用途 |
|---|---|---|
| POST | /v1/songs | 新しい曲を依頼します。 |
| GET | /v1/songs/{id} | 最新の全フィールドを含む曲を取得します。 |
| GET | /v1/songs | アカウントの曲を絞り込みとページングで一覧します。 |
| GET | /v1/songs/{id}/lyrics | 歌詞だけをプレーンテキストで取得します。 |
| GET | /v1/songs/{id}/audio | プレビューまたは完成音源の署名付きダウンロードリンク。 |
| POST | /v1/songs/{id}/regenerate | 無料の再生成を開始します。 |
| POST | /v1/songs/{id}/checkout | エンドユーザー向けの決済ページを作成します。 |
| POST | /v1/songs/{id}/unlock | 曲を直接解放し、アカウントに請求します。 |
| GET | /v1/options | 場面、雰囲気、スタイル、声、言語で使える値の一覧。 |
| GET | /v1/account | 残高、上限、開放されているドメイン。 |
| DELETE | /v1/songs/{id} | まだ完成していない曲をキャンセルします。 |
POST /v1/songs は依頼内容を受け取り、すぐに処理を始めます。必須は三つのフィールドだけで、その他は妥当な既定値があるか、場面に合わせて自動的に選ばれます。
| フィールド | 型 | 説明 |
|---|---|---|
| string | 必須 | 場面。使える値は /v1/options から取得します。 |
| string | 必須 | 歌う相手の名前。歌詞の中で使われます。 |
| string | 必須 | その人についての具体的な情報。40文字から4000文字。品質を決めるフィールドです。 |
| string | 任意 | 依頼者と受け取る人の関係。例えば姉、同僚、パートナー。 |
| string | 任意 | 歌う言語。既定値は ja です。 |
| string | 任意 | 基本の雰囲気。指定がなければ場面に合うものを選びます。 |
| string | 任意 | 音楽スタイル。指定がなければ場面と雰囲気に合うものを選びます。 |
| string | 任意 | 歌い手の声。指定がなければ場面に合うものを選びます。 |
| string | 任意 | 曲の中で伝えたいメッセージ。 |
| string | 任意 | 他に当てはまらない内容の自由記述。例えばテンポの希望など。 |
| string | 任意 | イベントの送信先となるHTTPSのURL。 |
| object | 任意 | 任意のキーと値の組。最大20件。そのまま返されます。 |
const res = await fetch("https://api.oriuta.jp/v1/songs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SONG_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
occasion: "anniversary",
recipient_name: "Mara",
relationship: "partner",
language: "ja",
mood: "warm",
details: "Ten years, three apartments, one very loud coffee machine.",
callback_url: "https://example.com/hooks/songs",
metadata: { order_id: "A-10423" },
}),
});
const song = await res.json();
console.log(song.id, song.status);
この呼び出しには費用がかかりません。課金は /unlock による解放、または完了した決済セッションの時点で発生します。
単一の曲を返すエンドポイントは、すべて同じオブジェクトを返します。まだ存在しないフィールドは null で、制作が進むにつれて埋まっていきます。
{
"id": "sng_3n8Kd2ZpQv",
"object": "song",
"status": "queued",
"created_at": "2026-09-16T09:41:02Z",
"occasion": "birthday",
"recipient_name": "Anna",
"relationship": "sister",
"language": "ja",
"mood": "happy",
"style": "pop",
"voice": "female",
"lyrics": null,
"preview_url": null,
"audio_url": null,
"duration_seconds": null,
"paid": false,
"price": { "amount": 2999, "currency": "JPY" },
"metadata": {},
"livemode": true
}
| フィールド | 型 | 説明 |
|---|---|---|
| string | 任意 | 一意のID。必ず sng_ で始まります。 |
| string | 任意 | 制作の現在の段階。次章を参照してください。 |
| string | 任意 | ヴァースとコーラスの表記を含む歌詞全文。支払い前でも無料です。 |
| string | 任意 | 冒頭45秒のMP3。支払いなしで常に利用できます。 |
| string | 任意 | 完成音源のMP3。署名付きで24時間有効。支払い後に埋まります。 |
| integer | 任意 | 完成音源の長さ(秒)。通常は120から240の間です。 |
| boolean | 任意 | 曲が解放されているかどうか。 |
| object | 任意 | 通貨の最小単位での金額と通貨コード。ここでは ¥2980。 |
| object | 任意 | 作成時に渡した内容がそのまま返ります。 |
| boolean | 任意 | テストキーでのリクエストの場合は false。 |
{
"id": "sng_3n8Kd2ZpQv",
"object": "song",
"status": "complete",
"created_at": "2026-09-16T09:41:02Z",
"completed_at": "2026-09-16T09:47:35Z",
"lyrics": "[Verse 1]\nAnna, six in the morning, chalk on your hands ...",
"preview_url": "https://cdn.oriuta.jp/preview/sng_3n8Kd2ZpQv.mp3",
"audio_url": "https://cdn.oriuta.jp/full/sng_3n8Kd2ZpQv.mp3?expires=1789412855&sig=...",
"duration_seconds": 184,
"paid": true,
"price": { "amount": 2999, "currency": "JPY" },
"metadata": { "order_id": "A-10423" },
"livemode": true
}
曲はこの順序で段階を進みます。逆戻りすることはなく、complete、failed、cancelled は終了状態です。
| ステータス | 値 | 意味 |
|---|---|---|
| queued | 受け付け済み。制作の空きを待っています。通常は数秒です。 | |
| writing_lyrics | 歌詞を執筆中です。 | |
| lyrics_ready | 歌詞が完成し、取得できます。通常は1分から2分後です。 | |
| generating_audio | ボーカル、アレンジ、ミックスを制作中です。 | |
| preview_ready | 冒頭45秒が利用可能になり、完成ファイルも用意できています。 | |
| complete | 支払い済みで、すべて納品されています。 | |
| failed | 制作が最終的に失敗しました。課金はなく、error フィールドに理由が入ります。 | |
| cancelled | 完成前にキャンセルされました。 |
制作が一度失敗しても、すぐに failed にはなりません。内部で数回やり直し、すべての試行が失敗したときに初めてあきらめます。そのため failed はまれで、出たときは本当に「この曲は届かない」という意味です。
GET /v1/songs/{id} は曲の現在の状態を返します。軽量なエンドポイントなので、レート上限の範囲内であれば1秒ごとの問い合わせにも耐えます。
curl -G https://api.oriuta.jp/v1/songs \
-H "Authorization: Bearer $SONG_API_KEY" \
-d status=complete \
-d limit=20 \
-d starting_after=sng_3n8Kd2ZpQv
一覧はカーソル方式です。新しいものから最大 limit 件(既定20件、最大100件)が返ります。has_more が true の場合は、next_cursor を次の呼び出しの starting_after に渡します。絞り込みには status、occasion、language、paid、created_after、created_before が使えます。
{
"object": "list",
"data": [
{ "id": "sng_9Wq1LmT4bR", "status": "complete", "recipient_name": "Jonas", "...": "..." },
{ "id": "sng_3n8Kd2ZpQv", "status": "complete", "recipient_name": "Anna", "...": "..." }
],
"has_more": true,
"next_cursor": "sng_3n8Kd2ZpQv"
}
歌詞は無料で、抜粋ではなく全文です。GET /v1/songs/{id}/lyrics がヴァースとコーラスの表記を含めて text/plain で返します。同じ歌詞は曲オブジェクトの lyrics フィールドにも入っています。
音源には二段階あります。プレビューは完成音源の冒頭45秒で、別に作ったデモではありません。同じ声、同じアレンジ、同じ歌詞です。支払いなしで利用でき、今後もそのままです。完成ファイルは解放後に GET /v1/songs/{id}/audio が返します。
どちらのURLも署名付きで24時間有効です。ダウンロード用であり、恒久的なリンク先ではありません。ファイルを長く使う場合は一度ダウンロードしてご自身で保管してください。エンドポイントを呼び直せば、いつでも新しいURLが得られます。
形式は常にMP3 320 kbit/sです。WAVが必要な場合は ?format=wav を付けてください。スタジオオプション付きのアカウントで利用できます。
結果に納得がいかない場合、再生成に費用はかかりません。POST /v1/songs/{id}/regenerate は同じIDで新しいバージョンを作り、ステータスを queued に戻します。前のバージョンは previous_versions に残ります。
curl https://api.oriuta.jp/v1/songs/sng_3n8Kd2ZpQv/regenerate \
-H "Authorization: Bearer $SONG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"keep_lyrics": false,
"reason": "voice_not_matching",
"note": "Please try a lower male voice and a slower tempo."
}'
keep_lyrics: true なら歌詞はそのままで、音源だけを作り直します。歌詞は良いのに声やテンポだけが合わなかったときの正しい方法です。false にすると歌詞も書き直します。
note フィールドはそのまま再生成に渡されるので、具体的な一文を書く価値があります。「もう少し低い男性の声で、ゆっくり」は効きますが、「もっと良くして」は効きません。納得のいく仕上がりになるまで再生成します。1曲あたり6回までは無料で、それを超える場合はご相談ください。
曲を解放する方法は、誰が支払うかによって二つあります。
POST /v1/songs/{id}/checkout は、ドメインの通貨とその国で一般的な決済手段を備えた決済ページを当社側に作ります。そこへお客さまを案内し、決済が完了すると song.paid イベントが届きます。
curl https://api.oriuta.jp/v1/songs/sng_3n8Kd2ZpQv/checkout \
-H "Authorization: Bearer $SONG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"success_url": "https://example.com/thanks?song=sng_3n8Kd2ZpQv",
"cancel_url": "https://example.com/cart"
}'
{
"object": "checkout_session",
"song": "sng_3n8Kd2ZpQv",
"url": "https://pay.oriuta.jp/c/cs_live_8Hd2Kq...",
"amount": 2999,
"currency": "JPY",
"expires_at": "2026-09-16T11:41:02Z"
}
まとめて請求するアカウントでは、POST /v1/songs/{id}/unlock が曲をただちに解放し、アカウントに ¥2980 を請求します。決済ページを経由しないので、自前のレジがある場合に便利です。
curl https://api.oriuta.jp/v1/songs/sng_3n8Kd2ZpQv/unlock \
-H "Authorization: Bearer $SONG_API_KEY" \
-X POST
どちらの場合も利用許諾は同じです。非独占ですが、明確に商用利用が可能です。完成した曲は、ご自身のサービスの一部として引き渡し、販売し、公開できます。
場面、雰囲気、スタイル、声、言語の一覧はときどき変わります。コードに直接書き込むのではなく、GET /v1/options を呼んで、レスポンスを数時間キャッシュしてください。
{
"object": "options",
"language": "ja",
"occasions": ["birthday", "wedding", "anniversary", "farewell", "funeral",
"christening", "graduation", "christmas", "declaration", "other"],
"moods": ["happy", "warm", "funny", "romantic", "gentle", "epic", "surprise_me"],
"styles": ["pop", "rock", "folk", "schlager", "hiphop", "ballad", "country",
"electronic", "jazz", "childrens", "surprise_me"],
"voices": ["female", "male", "duet", "choir", "childrens", "surprise_me"],
"languages": ["de", "en", "dk", "nl", "it", "se", "fr", "es", "no", "pl", "fi", "is", "jp"]
}
これらの値はいずれも省略できます。surprise_me は穴埋めではなく本当の指示で、その場合は場面と具体的な情報に合うものを当社が意図して選びます。
作成時に callback_url を指定すると、すべてのイベントをPOSTで送信します。問い合わせも待ち時間もなくなるため、こちらを推奨します。
| イベント | 種別 | 発生条件 |
|---|---|---|
| song.lyrics_ready | 歌詞が完成したとき。 | |
| song.preview_ready | 45秒のプレビューが利用可能になったとき。 | |
| song.completed | 完成音源が納品されたとき。 | |
| song.failed | 制作が最終的に失敗したとき。 | |
| song.regenerated | 再生成が完了したとき。 | |
| song.paid | 支払いが確認され、曲が解放されたとき。 |
{
"id": "evt_5Tb7Rn2WqX",
"object": "event",
"type": "song.completed",
"created_at": "2026-09-16T09:47:35Z",
"data": {
"object": {
"id": "sng_3n8Kd2ZpQv",
"object": "song",
"status": "complete",
"audio_url": "https://cdn.oriuta.jp/full/sng_3n8Kd2ZpQv.mp3?expires=1789412855&sig=...",
"...": "..."
}
}
}
各配信には、タイムスタンプと、タイムスタンプ、ピリオド、生のボディに対するHMAC-SHA256を含むヘッダーが付きます。内容を信頼する前に検証し、5分より古いものは拒否してください。
X-Song-Signature: t=1789412855,v1=7f2c1d9a4b6e8035c1f7a29d4e5b0c8371a6d2f94e8b3c07a15d9e2f6b4c8a01
import hashlib, hmac, os, time
from flask import Flask, request, abort
SECRET = os.environ["SONG_WEBHOOK_SECRET"].encode()
app = Flask(__name__)
@app.post("/hooks/songs")
def hook():
header = request.headers.get("X-Song-Signature", "")
parts = dict(p.split("=", 1) for p in header.split(",") if "=" in p)
timestamp, signature = parts.get("t", ""), parts.get("v1", "")
if abs(time.time() - int(timestamp or 0)) > 300:
abort(400) # older than five minutes, treat as replay
expected = hmac.new(
SECRET, (timestamp + "." + request.get_data(as_text=True)).encode(),
hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(expected, signature):
abort(400)
event = request.get_json()
if event["type"] == "song.completed":
store(event["data"]["object"])
return "", 200
10秒以内の2xxレスポンスを期待します。返らない場合は24時間かけて8回、間隔を広げながら再送します。したがって配信は重複することがあり、まれに順序が前後します。受信側は冪等に作り、到着時刻ではなく created_at フィールドを信頼してください。
すべてのPOSTは Idempotency-Key ヘッダーを受け付けます。値は一意であれば何でもよく、通常はUUIDです。同じキーが24時間以内に再び来た場合は、二つ目の曲を作らずに最初のレスポンスを返します。
curl https://api.oriuta.jp/v1/songs \
-H "Authorization: Bearer $SONG_API_KEY" \
-H "Idempotency-Key: 9f1c7c2e-0a3b-4c8d-9e21-5f7a1b6c3d40" \
-H "Content-Type: application/json" \
-d '{ "occasion": "birthday", "recipient_name": "Anna", "language": "ja", "details": "..." }'
これはネットワーク障害時にまさに必要となる保護です。レスポンスが失われてコードがリクエストを再送しても、できる曲は一つだけです。同じキーで異なるボディを送った場合は、409とエラー種別 conflict を返します。
エラーは常に同じ形で返ります。機械可読な type と code、読める形のメッセージ、該当する場合はフィールドの指定が入ります。お問い合わせの際は request_id を添えていただければ、ログから該当の呼び出しを見つけられます。
{
"error": {
"type": "validation_error",
"code": "details_too_short",
"message": "details must contain at least 40 characters so the song has something to work with",
"param": "details",
"request_id": "req_2Lm9Xc4Kd1"
}
}
| 種別 | HTTP | 意味 |
|---|---|---|
| 400 | invalid_request | リクエストの形式が壊れています。不正なJSONや未知のフィールドなど。 |
| 401 | authentication_error | キーがない、期限切れ、または無効化されています。 |
| 403 | permission_error | キーは有効ですが、このドメインまたはエンドポイントに開放されていません。 |
| 404 | not_found | 指定されたIDがこのアカウントのものではないか、存在しません。 |
| 409 | conflict | 操作が現在の状態と合いません。キャンセル済みの曲の解放など。 |
| 422 | validation_error | 形式は正しいものの値が使えません。details が短すぎる場合など。 |
| 429 | rate_limit | リクエストが多すぎるか、同時制作が多すぎます。 |
| 500 | api_error | 当社側のエラーです。間隔を広げて再試行してください。 |
429と5xxでは再試行に意味があります。指数的に間隔を広げ、わずかなランダム性を加えるのが望ましい方法です。429以外の4xxでは意味がありません。同じリクエストは再び失敗します。
| 項目 | 値 | 対象 |
|---|---|---|
| 60 / min | 全エンドポイント合計の、キーごとの1分あたりリクエスト数。 | |
| 10 | 同時制作数。超過分はキューに入ります。 | |
| 64 KB | リクエストボディの最大サイズ。 | |
| 40 - 4000 | details フィールドの文字数の下限と上限。 | |
| 90 | 曲と入力データを保持する日数。その後は削除されます。 | |
| 24 h | 冪等キーが以前のレスポンスを返す期間。 |
現在の状況はすべてのレスポンスのヘッダーに入るので、推測する必要はありません。
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1789412880
X-Concurrent-Limit: 10
X-Concurrent-Running: 3
上限の引き上げは問題ありません。初期設定がこうなっているだけです。件数が増えてきたら二行ほどお知らせください、引き上げます。
メジャーバージョンはパスに入り、安定して変わりません。v1 の中では追加のみの変更しか行いません。新しいフィールド、一覧への新しい値、新しいエンドポイントです。既存のフィールドが消えたり意味が変わったりすることはありません。
さらに確実にしたい場合は、ヘッダーで日付を固定できます。ヘッダーがなければ常に最新の挙動になります。
X-Song-Version: 2026-09-01
レスポンスの未知のフィールドは、エラーにせず無視するように実装してください。当社がクライアント側に置く唯一の前提です。
接頭辞 sk_test_ のキーはまったく同じエンドポイントを通りますが、実際の制作は始まらず、費用もかかりません。数秒後に固定のデモ歌詞とデモ音源が返り、すべてのオブジェクトに livemode: false が入ります。
これにより厄介なケースも練習できます。recipient_name に特定の名前を入れると結果を強制できます。test_fail は failed、test_slow は約10分かかる制作、test_ratelimit は429のレスポンスになります。実際の障害を待たずにエラー処理を検証できます。
Webhookもテストモードで動作します。署名の仕組みは同じで、専用のシークレットが割り当てられます。
解放とともに、完成した曲について非独占ながら明確に商用の利用許諾が与えられます。引き渡し、販売、公の場での上演、ご自身の製品への組み込みが可能です。非独占とは、当社も例えば作例として音源を利用する権利を保持するという意味です。
人工知能が作った音楽の著作権について、多くの法域ではまだ確定した答えがありません。利用許諾は契約として保証しますが、その音源に第三者に対抗できる独立した著作権が生じるとまでは保証できません。それに依存する場合は、事前にご確認ください。
入力データと完成した曲は90日間保持し、その後削除します。個別の曲を早く削除するには DELETE /v1/songs/{id} を使います。details の内容はその1曲の制作にのみ使用し、自社モデルの学習には決して使いません。
お客さまのお客さまのデータを当社に渡す場合、貴社が管理者、当社が処理者となります。データ処理契約はご請求に応じて提供します。
ご質問、上限の引き上げ、データ処理契約、特殊なケースは songs@maxkuch.com までどうぞ。技術的な問題の場合はエラーレスポンスの request_id を添えてください。該当の呼び出しがすぐに見つかります。
AIエージェントからの連携には、Model Context Protocolのサーバーもあります。詳細は /mcp/ をご覧ください。REST APIと同じキーで使えます。
キーは手作業で発行しています。ご計画、想定件数、対応言語を短くお知らせいただければ十分で、通常は一営業日で開通します。