오류와 멱등성
하나의 오류 응답 구조, 안정적인 코드, 그리고 실제로 돈을 지켜주는 멱등성.
아직 사용할 수 없습니다 — api.baynoy.com 도메인이 조회되지 않으므로 아래 예제는 지금 실행되지 않습니다. 이 형식은 확정되었습니다. 지금 이대로 설계하시면 라이브 키로 전환할 때 달라지는 것이 없습니다.
One error envelope
Every non-2xx response carries {"error": {"code", "message", "details?"}}. Branch on code — it is a stable identifier. Never branch on message: messages are for humans and they change.
try {
await baynoy.payouts.create({ amount: 250000, currency: "EUR", beneficiary: "ben_123" },
{ idempotencyKey: key });
} catch (err) {
switch (err.code) {
case "insufficient_funds": return showTopUp();
case "beneficiary_cooldown": return showCooldown(err.details.availableAt);
case "idempotency_key_reused": return; // already done — do nothing
case "rate_limited": return retryAfter(err.details.retryAfterMs);
default: throw err; // unknown codes are bugs, not flows
}
}Idempotency is not optional on money
Financial POSTs require an Idempotency-Key scoped to your account and endpoint. The same key with the same body returns the first result; the same key with a different body is a conflict. Generate the key before the first attempt and reuse it for every retry of that same intent.
curl https://api.baynoy.com/v1/payouts \\
-H "Authorization: Bearer bk_test_..." \\
-H "Idempotency-Key: 7c1f0b6e-..." \\
-d amount=250000 -d currency=EUR -d beneficiary=ben_123
# same key + same body -> the original result, no second payout
# same key + other body -> 409 idempotency_key_reusedRetries and rate limits
Retry 5xx and rate_limited with exponential backoff and jitter; never retry a 4xx other than rate_limited without changing something. Rate-limit responses carry the wait time in details — respect it rather than guessing.