griffnode 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +9 -0
- data/LICENSE +17 -0
- data/README.md +24 -0
- data/Rakefile +10 -0
- data/docs/Account.md +22 -0
- data/docs/AccountApi.md +339 -0
- data/docs/AccountLimits.md +22 -0
- data/docs/AccountPlan.md +24 -0
- data/docs/AccountUsage.md +22 -0
- data/docs/Balance.md +24 -0
- data/docs/BillingApi.md +75 -0
- data/docs/CreateBillingCheckoutRequest.md +22 -0
- data/docs/CreateDetailedTransactionRequest.md +32 -0
- data/docs/CreateTransactionRequest.md +30 -0
- data/docs/CryptoSymbol.md +15 -0
- data/docs/Cryptocurrency.md +26 -0
- data/docs/DefaultApi.md +78 -0
- data/docs/Error.md +22 -0
- data/docs/FiatCurrency.md +15 -0
- data/docs/GetAccount200Response.md +20 -0
- data/docs/GetHealth200Response.md +22 -0
- data/docs/GetPrices200Response.md +20 -0
- data/docs/GetPrices200ResponseData.md +22 -0
- data/docs/GetStats200Response.md +20 -0
- data/docs/GetStats200ResponseData.md +24 -0
- data/docs/InlineObject.md +24 -0
- data/docs/InlineObjectAllOfExistingTransaction.md +22 -0
- data/docs/Invoice.md +34 -0
- data/docs/LineItem.md +22 -0
- data/docs/ListBalances200Response.md +20 -0
- data/docs/ListBalances200ResponseData.md +18 -0
- data/docs/ListCryptocurrencies200Response.md +20 -0
- data/docs/ListCryptocurrencies200ResponseData.md +20 -0
- data/docs/ListInvoices200Response.md +20 -0
- data/docs/ListInvoices200ResponseData.md +20 -0
- data/docs/ListPlans200Response.md +20 -0
- data/docs/ListPlans200ResponseData.md +20 -0
- data/docs/ListTransactions200Response.md +20 -0
- data/docs/ListTransactions200ResponseData.md +20 -0
- data/docs/MarketDataApi.md +202 -0
- data/docs/Pagination.md +22 -0
- data/docs/PaymentSplit.md +28 -0
- data/docs/Plan.md +38 -0
- data/docs/PlanTier.md +15 -0
- data/docs/SystemApi.md +139 -0
- data/docs/Transaction.md +66 -0
- data/docs/TransactionEnvelope.md +20 -0
- data/docs/TransactionStatus.md +15 -0
- data/docs/TransactionsApi.md +295 -0
- data/docs/WebhookPayload.md +40 -0
- data/git_push.sh +57 -0
- data/griffnode.gemspec +43 -0
- data/lib/griffnode/api/account_api.rb +315 -0
- data/lib/griffnode/api/billing_api.rb +88 -0
- data/lib/griffnode/api/default_api.rb +84 -0
- data/lib/griffnode/api/market_data_api.rb +187 -0
- data/lib/griffnode/api/system_api.rb +158 -0
- data/lib/griffnode/api/transactions_api.rb +300 -0
- data/lib/griffnode/api_client.rb +394 -0
- data/lib/griffnode/api_error.rb +58 -0
- data/lib/griffnode/configuration.rb +308 -0
- data/lib/griffnode/models/account.rb +232 -0
- data/lib/griffnode/models/account_limits.rb +232 -0
- data/lib/griffnode/models/account_plan.rb +264 -0
- data/lib/griffnode/models/account_usage.rb +234 -0
- data/lib/griffnode/models/balance.rb +241 -0
- data/lib/griffnode/models/create_billing_checkout_request.rb +284 -0
- data/lib/griffnode/models/create_detailed_transaction_request.rb +349 -0
- data/lib/griffnode/models/create_transaction_request.rb +313 -0
- data/lib/griffnode/models/crypto_symbol.rb +53 -0
- data/lib/griffnode/models/cryptocurrency.rb +284 -0
- data/lib/griffnode/models/error.rb +251 -0
- data/lib/griffnode/models/fiat_currency.rb +42 -0
- data/lib/griffnode/models/get_account200_response.rb +233 -0
- data/lib/griffnode/models/get_health200_response.rb +232 -0
- data/lib/griffnode/models/get_prices200_response.rb +233 -0
- data/lib/griffnode/models/get_prices200_response_data.rb +238 -0
- data/lib/griffnode/models/get_stats200_response.rb +233 -0
- data/lib/griffnode/models/get_stats200_response_data.rb +241 -0
- data/lib/griffnode/models/inline_object.rb +267 -0
- data/lib/griffnode/models/inline_object_all_of_existing_transaction.rb +254 -0
- data/lib/griffnode/models/invoice.rb +311 -0
- data/lib/griffnode/models/line_item.rb +267 -0
- data/lib/griffnode/models/list_balances200_response.rb +233 -0
- data/lib/griffnode/models/list_balances200_response_data.rb +216 -0
- data/lib/griffnode/models/list_cryptocurrencies200_response.rb +233 -0
- data/lib/griffnode/models/list_cryptocurrencies200_response_data.rb +225 -0
- data/lib/griffnode/models/list_invoices200_response.rb +233 -0
- data/lib/griffnode/models/list_invoices200_response_data.rb +225 -0
- data/lib/griffnode/models/list_plans200_response.rb +233 -0
- data/lib/griffnode/models/list_plans200_response_data.rb +227 -0
- data/lib/griffnode/models/list_transactions200_response.rb +233 -0
- data/lib/griffnode/models/list_transactions200_response_data.rb +239 -0
- data/lib/griffnode/models/pagination.rb +253 -0
- data/lib/griffnode/models/payment_split.rb +262 -0
- data/lib/griffnode/models/plan.rb +330 -0
- data/lib/griffnode/models/plan_tier.rb +42 -0
- data/lib/griffnode/models/transaction.rb +535 -0
- data/lib/griffnode/models/transaction_envelope.rb +233 -0
- data/lib/griffnode/models/transaction_status.rb +44 -0
- data/lib/griffnode/models/webhook_payload.rb +387 -0
- data/lib/griffnode/version.rb +15 -0
- data/lib/griffnode.rb +84 -0
- data/openapi.yaml +791 -0
- data/openapitools.json +15 -0
- data/spec/api/account_api_spec.rb +87 -0
- data/spec/api/billing_api_spec.rb +46 -0
- data/spec/api/default_api_spec.rb +47 -0
- data/spec/api/market_data_api_spec.rb +65 -0
- data/spec/api/system_api_spec.rb +60 -0
- data/spec/api/transactions_api_spec.rb +84 -0
- data/spec/models/account_limits_spec.rb +48 -0
- data/spec/models/account_plan_spec.rb +54 -0
- data/spec/models/account_spec.rb +48 -0
- data/spec/models/account_usage_spec.rb +48 -0
- data/spec/models/balance_spec.rb +54 -0
- data/spec/models/create_billing_checkout_request_spec.rb +48 -0
- data/spec/models/create_detailed_transaction_request_spec.rb +78 -0
- data/spec/models/create_transaction_request_spec.rb +72 -0
- data/spec/models/crypto_symbol_spec.rb +30 -0
- data/spec/models/cryptocurrency_spec.rb +64 -0
- data/spec/models/error_spec.rb +48 -0
- data/spec/models/fiat_currency_spec.rb +30 -0
- data/spec/models/get_account200_response_spec.rb +42 -0
- data/spec/models/get_health200_response_spec.rb +48 -0
- data/spec/models/get_prices200_response_data_spec.rb +48 -0
- data/spec/models/get_prices200_response_spec.rb +42 -0
- data/spec/models/get_stats200_response_data_spec.rb +54 -0
- data/spec/models/get_stats200_response_spec.rb +42 -0
- data/spec/models/inline_object_all_of_existing_transaction_spec.rb +48 -0
- data/spec/models/inline_object_spec.rb +54 -0
- data/spec/models/invoice_spec.rb +84 -0
- data/spec/models/line_item_spec.rb +48 -0
- data/spec/models/list_balances200_response_data_spec.rb +36 -0
- data/spec/models/list_balances200_response_spec.rb +42 -0
- data/spec/models/list_cryptocurrencies200_response_data_spec.rb +42 -0
- data/spec/models/list_cryptocurrencies200_response_spec.rb +42 -0
- data/spec/models/list_invoices200_response_data_spec.rb +42 -0
- data/spec/models/list_invoices200_response_spec.rb +42 -0
- data/spec/models/list_plans200_response_data_spec.rb +42 -0
- data/spec/models/list_plans200_response_spec.rb +42 -0
- data/spec/models/list_transactions200_response_data_spec.rb +42 -0
- data/spec/models/list_transactions200_response_spec.rb +42 -0
- data/spec/models/pagination_spec.rb +48 -0
- data/spec/models/payment_split_spec.rb +66 -0
- data/spec/models/plan_spec.rb +96 -0
- data/spec/models/plan_tier_spec.rb +30 -0
- data/spec/models/transaction_envelope_spec.rb +42 -0
- data/spec/models/transaction_spec.rb +184 -0
- data/spec/models/transaction_status_spec.rb +30 -0
- data/spec/models/webhook_payload_spec.rb +106 -0
- data/spec/spec_helper.rb +111 -0
- metadata +286 -0
data/openapi.yaml
ADDED
|
@@ -0,0 +1,791 @@
|
|
|
1
|
+
openapi: 3.1.0
|
|
2
|
+
|
|
3
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
# GriffNode Public Merchant API — SINGLE SOURCE OF TRUTH
|
|
5
|
+
#
|
|
6
|
+
# This file is CANONICAL. Code, docs, SDKs, and plugins are reconciled TO it.
|
|
7
|
+
# Governance: docs/sdk/api-contract-governance.md (the contract is FROZEN).
|
|
8
|
+
#
|
|
9
|
+
# This spec describes the cleaned-up v1 TARGET (decided: clean break + trim + /v1):
|
|
10
|
+
# - transaction_id everywhere (the old `txid` on create/get is removed)
|
|
11
|
+
# - currency_fiat everywhere (the old `currency` on create/get is removed)
|
|
12
|
+
# - one pagination style: limit + offset, with a { limit, offset, total } block
|
|
13
|
+
# - one curated Transaction schema for create/get/list (capability tokens,
|
|
14
|
+
# client_ip, address_index, and other internal fields are NOT exposed)
|
|
15
|
+
# - all paths under /v1
|
|
16
|
+
# Migration status of the Go code → this spec is tracked in api-inconsistencies.md.
|
|
17
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
info:
|
|
20
|
+
title: GriffNode API
|
|
21
|
+
version: "1.0.1"
|
|
22
|
+
description: >
|
|
23
|
+
Accept Bitcoin, Litecoin, Dogecoin, Dash, Ethereum and ERC-20 tokens.
|
|
24
|
+
Server-to-server, authenticated with a secret API key
|
|
25
|
+
(`Authorization: Bearer sk_live_…` for live, or `sk_test_…` for test mode — same base URL).
|
|
26
|
+
All monetary amounts in API responses are JSON numbers; **webhook** amounts are
|
|
27
|
+
strings to preserve decimal precision (see the `webhooks` section).
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
**Rate limits.** Every request is rate-limited per API key in two windows — per minute
|
|
31
|
+
and per hour — by plan tier (min/hour): starter 30/500, business 100/2000, professional
|
|
32
|
+
300/5000, enterprise 1000/20000. Every response carries `X-RateLimit-Limit`,
|
|
33
|
+
`X-RateLimit-Remaining` and `X-RateLimit-Reset` (Unix seconds) for the per-minute window.
|
|
34
|
+
On `429` the body is `error: "RATE_LIMIT_EXCEEDED"` (either window) with a `Retry-After`
|
|
35
|
+
header (seconds) — clients should retry after it. A separate `429` with
|
|
36
|
+
`error: "MONTHLY_LIMIT_REACHED"` means the plan's monthly transaction quota (not the
|
|
37
|
+
request rate).
|
|
38
|
+
license:
|
|
39
|
+
name: Apache-2.0
|
|
40
|
+
contact:
|
|
41
|
+
name: GriffNode Developers
|
|
42
|
+
url: https://griffnode.com
|
|
43
|
+
|
|
44
|
+
servers:
|
|
45
|
+
- url: https://api.griffnode.com/v1
|
|
46
|
+
description: >
|
|
47
|
+
Single base URL for both live and test traffic. A live secret key (`sk_live_`)
|
|
48
|
+
settles real funds on mainnet; a test secret key (`sk_test_`) runs in test mode
|
|
49
|
+
with no real funds. There is no separate sandbox host.
|
|
50
|
+
|
|
51
|
+
security:
|
|
52
|
+
- SecretKey: []
|
|
53
|
+
|
|
54
|
+
tags:
|
|
55
|
+
- name: Transactions
|
|
56
|
+
description: Create and read merchant payment transactions.
|
|
57
|
+
- name: Market Data
|
|
58
|
+
description: Live prices and the supported-currency catalogue.
|
|
59
|
+
- name: Account
|
|
60
|
+
description: Merchant plan, usage, balances, stats and invoices.
|
|
61
|
+
- name: Billing
|
|
62
|
+
description: Plan upgrades and account top-ups.
|
|
63
|
+
- name: System
|
|
64
|
+
description: Health and hosted-checkout redirect.
|
|
65
|
+
|
|
66
|
+
# ═════════════════════════════════════════════════════════════════════════════
|
|
67
|
+
paths:
|
|
68
|
+
|
|
69
|
+
/health:
|
|
70
|
+
get:
|
|
71
|
+
operationId: getHealth
|
|
72
|
+
tags: [System]
|
|
73
|
+
summary: API health check
|
|
74
|
+
security: []
|
|
75
|
+
responses:
|
|
76
|
+
"200":
|
|
77
|
+
description: Service status (intentionally NOT wrapped in the success envelope).
|
|
78
|
+
content:
|
|
79
|
+
application/json:
|
|
80
|
+
schema:
|
|
81
|
+
type: object
|
|
82
|
+
properties:
|
|
83
|
+
status: { type: string, examples: ["operational"] }
|
|
84
|
+
service: { type: string, examples: ["GriffNode API"] }
|
|
85
|
+
version: { type: string, examples: ["1.0.0"] }
|
|
86
|
+
|
|
87
|
+
/pay:
|
|
88
|
+
get:
|
|
89
|
+
operationId: hostedCheckoutRedirect
|
|
90
|
+
tags: [System]
|
|
91
|
+
summary: Hosted-checkout redirect (browser flow, publishable key)
|
|
92
|
+
description: >
|
|
93
|
+
Browser-facing redirect to the hosted payment page, authenticated by a
|
|
94
|
+
**publishable** key in the query string (safe to expose client-side).
|
|
95
|
+
Not used by the server-side SDKs — included for completeness.
|
|
96
|
+
security: []
|
|
97
|
+
parameters:
|
|
98
|
+
- { name: pk, in: query, required: true, schema: { type: string }, description: "Publishable key, pk_live_… / pk_test_…" }
|
|
99
|
+
- { name: amount, in: query, required: true, schema: { type: string }, description: "Fiat amount (≥ 1.00 USD equivalent)." }
|
|
100
|
+
- { name: crypto, in: query, required: true, schema: { $ref: "#/components/schemas/CryptoSymbol" } }
|
|
101
|
+
- { name: link, in: query, required: false, schema: { type: string }, description: "Payment-link slug for attribution." }
|
|
102
|
+
responses:
|
|
103
|
+
"302":
|
|
104
|
+
description: Redirect to https://griffnode.com/transaction/{transaction_id}
|
|
105
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
106
|
+
|
|
107
|
+
/transactions/create:
|
|
108
|
+
post:
|
|
109
|
+
operationId: createTransaction
|
|
110
|
+
tags: [Transactions]
|
|
111
|
+
summary: Create a payment transaction
|
|
112
|
+
parameters:
|
|
113
|
+
- $ref: "#/components/parameters/IdempotencyKey"
|
|
114
|
+
requestBody:
|
|
115
|
+
required: true
|
|
116
|
+
content:
|
|
117
|
+
application/json:
|
|
118
|
+
schema: { $ref: "#/components/schemas/CreateTransactionRequest" }
|
|
119
|
+
responses:
|
|
120
|
+
"201":
|
|
121
|
+
description: Transaction created.
|
|
122
|
+
content:
|
|
123
|
+
application/json:
|
|
124
|
+
schema: { $ref: "#/components/schemas/TransactionEnvelope" }
|
|
125
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
126
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
127
|
+
"402": { $ref: "#/components/responses/InsufficientBalance" }
|
|
128
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
129
|
+
"409": { $ref: "#/components/responses/ActiveTransactionExists" }
|
|
130
|
+
"429": { $ref: "#/components/responses/TooManyRequests" }
|
|
131
|
+
|
|
132
|
+
/transactions/create-detailed:
|
|
133
|
+
post:
|
|
134
|
+
operationId: createDetailedTransaction
|
|
135
|
+
tags: [Transactions]
|
|
136
|
+
summary: Create an itemized transaction (Professional/Enterprise plans)
|
|
137
|
+
parameters:
|
|
138
|
+
- $ref: "#/components/parameters/IdempotencyKey"
|
|
139
|
+
requestBody:
|
|
140
|
+
required: true
|
|
141
|
+
content:
|
|
142
|
+
application/json:
|
|
143
|
+
schema: { $ref: "#/components/schemas/CreateDetailedTransactionRequest" }
|
|
144
|
+
responses:
|
|
145
|
+
"201":
|
|
146
|
+
description: Transaction created.
|
|
147
|
+
content:
|
|
148
|
+
application/json:
|
|
149
|
+
schema: { $ref: "#/components/schemas/TransactionEnvelope" }
|
|
150
|
+
"400": { $ref: "#/components/responses/BadRequest" }
|
|
151
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
152
|
+
"402": { $ref: "#/components/responses/InsufficientBalance" }
|
|
153
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
154
|
+
"429": { $ref: "#/components/responses/TooManyRequests" }
|
|
155
|
+
|
|
156
|
+
/transactions/list:
|
|
157
|
+
get:
|
|
158
|
+
operationId: listTransactions
|
|
159
|
+
tags: [Transactions]
|
|
160
|
+
summary: List the merchant's transactions (newest first)
|
|
161
|
+
parameters:
|
|
162
|
+
- $ref: "#/components/parameters/Limit"
|
|
163
|
+
- $ref: "#/components/parameters/Offset"
|
|
164
|
+
- { name: status, in: query, required: false, schema: { $ref: "#/components/schemas/TransactionStatus" } }
|
|
165
|
+
- { name: crypto, in: query, required: false, schema: { $ref: "#/components/schemas/CryptoSymbol" } }
|
|
166
|
+
responses:
|
|
167
|
+
"200":
|
|
168
|
+
description: A page of transactions.
|
|
169
|
+
content:
|
|
170
|
+
application/json:
|
|
171
|
+
schema:
|
|
172
|
+
type: object
|
|
173
|
+
required: [success, data]
|
|
174
|
+
properties:
|
|
175
|
+
success: { const: true }
|
|
176
|
+
data:
|
|
177
|
+
type: object
|
|
178
|
+
required: [transactions, pagination]
|
|
179
|
+
properties:
|
|
180
|
+
transactions:
|
|
181
|
+
type: array
|
|
182
|
+
items: { $ref: "#/components/schemas/Transaction" }
|
|
183
|
+
pagination: { $ref: "#/components/schemas/Pagination" }
|
|
184
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
185
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
186
|
+
|
|
187
|
+
/transactions/{transaction_id}:
|
|
188
|
+
get:
|
|
189
|
+
operationId: getTransaction
|
|
190
|
+
tags: [Transactions]
|
|
191
|
+
summary: Retrieve a single transaction
|
|
192
|
+
parameters:
|
|
193
|
+
- name: transaction_id
|
|
194
|
+
in: path
|
|
195
|
+
required: true
|
|
196
|
+
schema: { type: string, examples: ["MTX-A1B2C3D4"] }
|
|
197
|
+
responses:
|
|
198
|
+
"200":
|
|
199
|
+
description: The transaction.
|
|
200
|
+
content:
|
|
201
|
+
application/json:
|
|
202
|
+
schema: { $ref: "#/components/schemas/TransactionEnvelope" }
|
|
203
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
204
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
205
|
+
"404": { $ref: "#/components/responses/NotFound" }
|
|
206
|
+
|
|
207
|
+
/prices:
|
|
208
|
+
get:
|
|
209
|
+
operationId: getPrices
|
|
210
|
+
tags: [Market Data]
|
|
211
|
+
summary: Current crypto and fiat exchange rates (USD-denominated)
|
|
212
|
+
responses:
|
|
213
|
+
"200":
|
|
214
|
+
description: Live rates.
|
|
215
|
+
content:
|
|
216
|
+
application/json:
|
|
217
|
+
schema:
|
|
218
|
+
type: object
|
|
219
|
+
required: [success, data]
|
|
220
|
+
properties:
|
|
221
|
+
success: { const: true }
|
|
222
|
+
data:
|
|
223
|
+
type: object
|
|
224
|
+
properties:
|
|
225
|
+
crypto:
|
|
226
|
+
type: object
|
|
227
|
+
additionalProperties: { type: number }
|
|
228
|
+
description: USD price per unit, keyed by crypto symbol (active coins only).
|
|
229
|
+
fiat:
|
|
230
|
+
type: object
|
|
231
|
+
additionalProperties: { type: number }
|
|
232
|
+
description: USD value of one unit of each fiat currency.
|
|
233
|
+
fetched_at: { type: string, format: date-time }
|
|
234
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
235
|
+
"500": { $ref: "#/components/responses/ServerError" }
|
|
236
|
+
|
|
237
|
+
/cryptos/list:
|
|
238
|
+
get:
|
|
239
|
+
operationId: listCryptocurrencies
|
|
240
|
+
tags: [Market Data]
|
|
241
|
+
summary: All supported cryptocurrencies and tokens
|
|
242
|
+
responses:
|
|
243
|
+
"200":
|
|
244
|
+
description: Supported-currency catalogue.
|
|
245
|
+
content:
|
|
246
|
+
application/json:
|
|
247
|
+
schema:
|
|
248
|
+
type: object
|
|
249
|
+
required: [success, data]
|
|
250
|
+
properties:
|
|
251
|
+
success: { const: true }
|
|
252
|
+
data:
|
|
253
|
+
type: object
|
|
254
|
+
properties:
|
|
255
|
+
cryptocurrencies:
|
|
256
|
+
type: array
|
|
257
|
+
items: { $ref: "#/components/schemas/Cryptocurrency" }
|
|
258
|
+
total: { type: integer }
|
|
259
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
260
|
+
|
|
261
|
+
/merchant/cryptos:
|
|
262
|
+
get:
|
|
263
|
+
operationId: listMerchantCryptocurrencies
|
|
264
|
+
tags: [Market Data]
|
|
265
|
+
summary: Cryptocurrencies this merchant has wallets configured for
|
|
266
|
+
responses:
|
|
267
|
+
"200":
|
|
268
|
+
description: The merchant's configured currencies.
|
|
269
|
+
content:
|
|
270
|
+
application/json:
|
|
271
|
+
schema:
|
|
272
|
+
type: object
|
|
273
|
+
required: [success, data]
|
|
274
|
+
properties:
|
|
275
|
+
success: { const: true }
|
|
276
|
+
data:
|
|
277
|
+
type: object
|
|
278
|
+
properties:
|
|
279
|
+
cryptocurrencies:
|
|
280
|
+
type: array
|
|
281
|
+
items: { $ref: "#/components/schemas/Cryptocurrency" }
|
|
282
|
+
total: { type: integer }
|
|
283
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
284
|
+
|
|
285
|
+
/account:
|
|
286
|
+
get:
|
|
287
|
+
operationId: getAccount
|
|
288
|
+
tags: [Account]
|
|
289
|
+
summary: Merchant plan, usage and limits
|
|
290
|
+
responses:
|
|
291
|
+
"200":
|
|
292
|
+
description: Account details.
|
|
293
|
+
content:
|
|
294
|
+
application/json:
|
|
295
|
+
schema:
|
|
296
|
+
type: object
|
|
297
|
+
required: [success, data]
|
|
298
|
+
properties:
|
|
299
|
+
success: { const: true }
|
|
300
|
+
data: { $ref: "#/components/schemas/Account" }
|
|
301
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
302
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
303
|
+
|
|
304
|
+
/plans:
|
|
305
|
+
get:
|
|
306
|
+
operationId: listPlans
|
|
307
|
+
tags: [Account]
|
|
308
|
+
summary: Plan catalogue and pricing
|
|
309
|
+
responses:
|
|
310
|
+
"200":
|
|
311
|
+
description: Plans.
|
|
312
|
+
content:
|
|
313
|
+
application/json:
|
|
314
|
+
schema:
|
|
315
|
+
type: object
|
|
316
|
+
required: [success, data]
|
|
317
|
+
properties:
|
|
318
|
+
success: { const: true }
|
|
319
|
+
data:
|
|
320
|
+
type: object
|
|
321
|
+
properties:
|
|
322
|
+
plans:
|
|
323
|
+
type: array
|
|
324
|
+
items: { $ref: "#/components/schemas/Plan" }
|
|
325
|
+
billing_cycles:
|
|
326
|
+
type: array
|
|
327
|
+
items: { type: string }
|
|
328
|
+
examples: [["monthly", "quarterly", "biannual", "yearly", "biennial"]]
|
|
329
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
330
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
331
|
+
|
|
332
|
+
/balances:
|
|
333
|
+
get:
|
|
334
|
+
operationId: listBalances
|
|
335
|
+
tags: [Account]
|
|
336
|
+
summary: On-platform balances (for overage/top-up; NOT crypto settlement)
|
|
337
|
+
responses:
|
|
338
|
+
"200":
|
|
339
|
+
description: Balances.
|
|
340
|
+
content:
|
|
341
|
+
application/json:
|
|
342
|
+
schema:
|
|
343
|
+
type: object
|
|
344
|
+
required: [success, data]
|
|
345
|
+
properties:
|
|
346
|
+
success: { const: true }
|
|
347
|
+
data:
|
|
348
|
+
type: object
|
|
349
|
+
properties:
|
|
350
|
+
balances:
|
|
351
|
+
type: array
|
|
352
|
+
items: { $ref: "#/components/schemas/Balance" }
|
|
353
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
354
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
355
|
+
|
|
356
|
+
/stats:
|
|
357
|
+
get:
|
|
358
|
+
operationId: getStats
|
|
359
|
+
tags: [Account]
|
|
360
|
+
summary: Merchant transaction analytics
|
|
361
|
+
responses:
|
|
362
|
+
"200":
|
|
363
|
+
description: Stats.
|
|
364
|
+
content:
|
|
365
|
+
application/json:
|
|
366
|
+
schema:
|
|
367
|
+
type: object
|
|
368
|
+
required: [success, data]
|
|
369
|
+
properties:
|
|
370
|
+
success: { const: true }
|
|
371
|
+
data:
|
|
372
|
+
type: object
|
|
373
|
+
properties:
|
|
374
|
+
total_transactions: { type: integer }
|
|
375
|
+
monthly_transactions: { type: integer }
|
|
376
|
+
total_volume_fiat: { type: number }
|
|
377
|
+
unique_customers: { type: integer }
|
|
378
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
379
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
380
|
+
|
|
381
|
+
/invoices:
|
|
382
|
+
get:
|
|
383
|
+
operationId: listInvoices
|
|
384
|
+
tags: [Account]
|
|
385
|
+
summary: GriffNode billing invoices (platform ↔ merchant)
|
|
386
|
+
parameters:
|
|
387
|
+
- $ref: "#/components/parameters/Limit"
|
|
388
|
+
- $ref: "#/components/parameters/Offset"
|
|
389
|
+
responses:
|
|
390
|
+
"200":
|
|
391
|
+
description: Invoices.
|
|
392
|
+
content:
|
|
393
|
+
application/json:
|
|
394
|
+
schema:
|
|
395
|
+
type: object
|
|
396
|
+
required: [success, data]
|
|
397
|
+
properties:
|
|
398
|
+
success: { const: true }
|
|
399
|
+
data:
|
|
400
|
+
type: object
|
|
401
|
+
properties:
|
|
402
|
+
invoices:
|
|
403
|
+
type: array
|
|
404
|
+
items: { $ref: "#/components/schemas/Invoice" }
|
|
405
|
+
pagination: { $ref: "#/components/schemas/Pagination" }
|
|
406
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
407
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
408
|
+
|
|
409
|
+
/billing/checkout:
|
|
410
|
+
post:
|
|
411
|
+
operationId: createBillingCheckout
|
|
412
|
+
tags: [Billing]
|
|
413
|
+
summary: Start a plan upgrade or account top-up
|
|
414
|
+
requestBody:
|
|
415
|
+
required: true
|
|
416
|
+
content:
|
|
417
|
+
application/json:
|
|
418
|
+
schema:
|
|
419
|
+
type: object
|
|
420
|
+
required: [tier]
|
|
421
|
+
properties:
|
|
422
|
+
tier: { $ref: "#/components/schemas/PlanTier" }
|
|
423
|
+
billing_months: { type: integer, minimum: 1, default: 1 }
|
|
424
|
+
payment_method: { type: string, default: "crypto" }
|
|
425
|
+
responses:
|
|
426
|
+
"201":
|
|
427
|
+
description: Billing transaction created.
|
|
428
|
+
content:
|
|
429
|
+
application/json:
|
|
430
|
+
schema: { $ref: "#/components/schemas/TransactionEnvelope" }
|
|
431
|
+
"401": { $ref: "#/components/responses/Unauthorized" }
|
|
432
|
+
"402": { $ref: "#/components/responses/InsufficientBalance" }
|
|
433
|
+
"403": { $ref: "#/components/responses/Forbidden" }
|
|
434
|
+
|
|
435
|
+
# ═════════════════════════════════════════════════════════════════════════════
|
|
436
|
+
# Webhooks (OpenAPI 3.1 top-level). Every SDK ships a verify() helper for the
|
|
437
|
+
# signature scheme below. NOTE: webhook amounts are STRINGS (precision-safe).
|
|
438
|
+
webhooks:
|
|
439
|
+
paymentEvent:
|
|
440
|
+
post:
|
|
441
|
+
operationId: paymentWebhook
|
|
442
|
+
summary: Payment lifecycle event delivered to the merchant's webhook URL
|
|
443
|
+
description: >
|
|
444
|
+
Signed with HMAC-SHA256 over the RAW request body. Verify by comparing
|
|
445
|
+
`X-GriffNode-Signature: sha256=<hex>` to
|
|
446
|
+
`hex(hmac_sha256(webhook_secret, raw_body))` using a constant-time compare.
|
|
447
|
+
Also sent: `X-GriffNode-Event` (the event type) and `X-Webhook-ID`
|
|
448
|
+
(unique delivery id — use for idempotency).
|
|
449
|
+
requestBody:
|
|
450
|
+
content:
|
|
451
|
+
application/json:
|
|
452
|
+
schema: { $ref: "#/components/schemas/WebhookPayload" }
|
|
453
|
+
responses:
|
|
454
|
+
"200":
|
|
455
|
+
description: Acknowledge within 15s. Non-2xx is retried with backoff.
|
|
456
|
+
|
|
457
|
+
# ═════════════════════════════════════════════════════════════════════════════
|
|
458
|
+
components:
|
|
459
|
+
|
|
460
|
+
securitySchemes:
|
|
461
|
+
SecretKey:
|
|
462
|
+
type: http
|
|
463
|
+
scheme: bearer
|
|
464
|
+
description: "Secret API key: `Authorization: Bearer sk_live_…` (or `sk_test_…`)."
|
|
465
|
+
|
|
466
|
+
parameters:
|
|
467
|
+
Limit:
|
|
468
|
+
name: limit
|
|
469
|
+
in: query
|
|
470
|
+
required: false
|
|
471
|
+
schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
|
|
472
|
+
Offset:
|
|
473
|
+
name: offset
|
|
474
|
+
in: query
|
|
475
|
+
required: false
|
|
476
|
+
schema: { type: integer, minimum: 0, default: 0 }
|
|
477
|
+
IdempotencyKey:
|
|
478
|
+
name: X-Idempotency-Key
|
|
479
|
+
in: header
|
|
480
|
+
required: false
|
|
481
|
+
schema: { type: string }
|
|
482
|
+
description: >
|
|
483
|
+
Optional unique key for a create request (e.g. a UUID). A retried create with the
|
|
484
|
+
same key returns the original transaction instead of creating a duplicate — send it
|
|
485
|
+
on every create so a network retry can't double-charge the customer.
|
|
486
|
+
|
|
487
|
+
schemas:
|
|
488
|
+
|
|
489
|
+
CryptoSymbol:
|
|
490
|
+
type: string
|
|
491
|
+
description: Supported coin/token symbol. /cryptos/list is authoritative at runtime.
|
|
492
|
+
enum: [BTC, LTC, DOGE, DASH, ETH, USDT, USDC, DAI, WBTC, SHIB, PEPE, LINK, UNI, AAVE, MKR]
|
|
493
|
+
|
|
494
|
+
FiatCurrency:
|
|
495
|
+
type: string
|
|
496
|
+
enum: [USD, PLN, EUR, GBP]
|
|
497
|
+
default: USD
|
|
498
|
+
|
|
499
|
+
TransactionStatus:
|
|
500
|
+
type: string
|
|
501
|
+
description: Public transaction status (internal sub-states are mapped to these).
|
|
502
|
+
enum: [pending, awaiting_confirmation, completed, partial, expired, failed]
|
|
503
|
+
|
|
504
|
+
PlanTier:
|
|
505
|
+
type: string
|
|
506
|
+
enum: [starter, business, professional, enterprise]
|
|
507
|
+
|
|
508
|
+
Metadata:
|
|
509
|
+
type: [object, "null"]
|
|
510
|
+
description: Free-form key/value (≤20 keys, string values ≤500 chars, ≤4 KB total).
|
|
511
|
+
additionalProperties: { type: string }
|
|
512
|
+
|
|
513
|
+
LineItem:
|
|
514
|
+
type: object
|
|
515
|
+
required: [name, price]
|
|
516
|
+
properties:
|
|
517
|
+
name: { type: string }
|
|
518
|
+
quantity: { type: integer, minimum: 1, default: 1 }
|
|
519
|
+
price: { type: number }
|
|
520
|
+
|
|
521
|
+
CreateTransactionRequest:
|
|
522
|
+
type: object
|
|
523
|
+
required: [crypto, amount]
|
|
524
|
+
properties:
|
|
525
|
+
crypto: { $ref: "#/components/schemas/CryptoSymbol" }
|
|
526
|
+
amount: { type: number, description: "Fiat amount (≥ 1.00 USD equivalent)." }
|
|
527
|
+
currency_fiat: { $ref: "#/components/schemas/FiatCurrency" }
|
|
528
|
+
metadata: { $ref: "#/components/schemas/Metadata" }
|
|
529
|
+
customer_email: { type: [string, "null"], format: email }
|
|
530
|
+
success_url: { type: [string, "null"], format: uri }
|
|
531
|
+
cancel_url: { type: [string, "null"], format: uri }
|
|
532
|
+
|
|
533
|
+
CreateDetailedTransactionRequest:
|
|
534
|
+
type: object
|
|
535
|
+
required: [crypto, items, order_id]
|
|
536
|
+
properties:
|
|
537
|
+
crypto: { $ref: "#/components/schemas/CryptoSymbol" }
|
|
538
|
+
currency_fiat: { $ref: "#/components/schemas/FiatCurrency" }
|
|
539
|
+
items:
|
|
540
|
+
type: array
|
|
541
|
+
minItems: 1
|
|
542
|
+
items: { $ref: "#/components/schemas/LineItem" }
|
|
543
|
+
order_id: { type: string }
|
|
544
|
+
metadata: { $ref: "#/components/schemas/Metadata" }
|
|
545
|
+
customer_email: { type: [string, "null"], format: email }
|
|
546
|
+
success_url: { type: [string, "null"], format: uri }
|
|
547
|
+
cancel_url: { type: [string, "null"], format: uri }
|
|
548
|
+
|
|
549
|
+
PaymentSplit:
|
|
550
|
+
type: object
|
|
551
|
+
description: One on-chain payment toward the transaction.
|
|
552
|
+
properties:
|
|
553
|
+
txid: { type: string, description: "On-chain transaction hash (blockchain id, NOT the GriffNode transaction_id)." }
|
|
554
|
+
amount_crypto: { type: number }
|
|
555
|
+
confirmations: { type: integer }
|
|
556
|
+
status: { type: string }
|
|
557
|
+
detected_at: { type: string, format: date-time }
|
|
558
|
+
confirmed_at: { type: [string, "null"], format: date-time }
|
|
559
|
+
|
|
560
|
+
Transaction:
|
|
561
|
+
type: object
|
|
562
|
+
description: >
|
|
563
|
+
The canonical, curated public view of a transaction (same shape from
|
|
564
|
+
create, get and list). Internal fields (capability tokens, client_ip,
|
|
565
|
+
address_index, derivation/db internals) are deliberately NOT exposed.
|
|
566
|
+
required: [transaction_id, status, crypto, amount_fiat, amount_usd, currency_fiat, created_at, expires_at]
|
|
567
|
+
properties:
|
|
568
|
+
transaction_id: { type: string, examples: ["MTX-A1B2C3D4"] }
|
|
569
|
+
status: { $ref: "#/components/schemas/TransactionStatus" }
|
|
570
|
+
type: { type: string, enum: [basic, detailed] }
|
|
571
|
+
crypto: { $ref: "#/components/schemas/CryptoSymbol" }
|
|
572
|
+
deposit_address: { type: string }
|
|
573
|
+
amount_crypto: { type: number }
|
|
574
|
+
amount_fiat: { type: number }
|
|
575
|
+
amount_usd: { type: number }
|
|
576
|
+
amount_paid: { type: number }
|
|
577
|
+
amount_remaining: { type: number }
|
|
578
|
+
currency_fiat: { $ref: "#/components/schemas/FiatCurrency" }
|
|
579
|
+
fiat_to_usd_rate: { type: number }
|
|
580
|
+
exchange_rate: { type: number, description: "USD per unit of crypto, locked at creation." }
|
|
581
|
+
confirmations_required: { type: integer }
|
|
582
|
+
payment_url: { type: string, format: uri }
|
|
583
|
+
order_id: { type: [string, "null"] }
|
|
584
|
+
customer_email: { type: [string, "null"] }
|
|
585
|
+
items:
|
|
586
|
+
type: [array, "null"]
|
|
587
|
+
items: { $ref: "#/components/schemas/LineItem" }
|
|
588
|
+
payments:
|
|
589
|
+
type: array
|
|
590
|
+
description: On-chain payments detected toward this transaction.
|
|
591
|
+
items: { $ref: "#/components/schemas/PaymentSplit" }
|
|
592
|
+
metadata: { $ref: "#/components/schemas/Metadata" }
|
|
593
|
+
success_url: { type: [string, "null"] }
|
|
594
|
+
cancel_url: { type: [string, "null"] }
|
|
595
|
+
created_at: { type: string, format: date-time }
|
|
596
|
+
updated_at: { type: string, format: date-time }
|
|
597
|
+
expires_at: { type: string, format: date-time }
|
|
598
|
+
|
|
599
|
+
TransactionEnvelope:
|
|
600
|
+
type: object
|
|
601
|
+
required: [success, data]
|
|
602
|
+
properties:
|
|
603
|
+
success: { const: true }
|
|
604
|
+
data: { $ref: "#/components/schemas/Transaction" }
|
|
605
|
+
|
|
606
|
+
Cryptocurrency:
|
|
607
|
+
type: object
|
|
608
|
+
properties:
|
|
609
|
+
symbol: { $ref: "#/components/schemas/CryptoSymbol" }
|
|
610
|
+
name: { type: string }
|
|
611
|
+
blockchain: { type: string, examples: ["bitcoin", "ethereum"] }
|
|
612
|
+
network: { type: string, examples: ["mainnet"] }
|
|
613
|
+
type: { type: string, enum: [coin, token] }
|
|
614
|
+
|
|
615
|
+
Account:
|
|
616
|
+
type: object
|
|
617
|
+
properties:
|
|
618
|
+
plan:
|
|
619
|
+
type: object
|
|
620
|
+
properties:
|
|
621
|
+
tier: { $ref: "#/components/schemas/PlanTier" }
|
|
622
|
+
billing_cycle: { type: string }
|
|
623
|
+
auto_renewal: { type: boolean }
|
|
624
|
+
expires_at: { type: [string, "null"], format: date-time }
|
|
625
|
+
usage:
|
|
626
|
+
type: object
|
|
627
|
+
properties:
|
|
628
|
+
monthly_transactions_used: { type: integer }
|
|
629
|
+
monthly_transaction_limit: { type: [integer, "null"], description: "null = unlimited." }
|
|
630
|
+
overage_cost_per_tx: { type: number }
|
|
631
|
+
limits:
|
|
632
|
+
type: object
|
|
633
|
+
properties:
|
|
634
|
+
api_rate_limit_per_minute: { type: integer }
|
|
635
|
+
api_rate_limit_per_hour: { type: integer }
|
|
636
|
+
webhook_support: { type: boolean }
|
|
637
|
+
|
|
638
|
+
Plan:
|
|
639
|
+
type: object
|
|
640
|
+
properties:
|
|
641
|
+
tier: { $ref: "#/components/schemas/PlanTier" }
|
|
642
|
+
monthly_price_usd: { type: [number, "null"] }
|
|
643
|
+
yearly_price_usd: { type: [number, "null"] }
|
|
644
|
+
monthly_transaction_limit: { type: [integer, "null"] }
|
|
645
|
+
overage_cost_per_tx: { type: number }
|
|
646
|
+
webhook_support: { type: boolean }
|
|
647
|
+
webhook_limit: { type: [integer, "null"] }
|
|
648
|
+
ip_whitelist: { type: boolean }
|
|
649
|
+
api_rate_limit_per_minute: { type: integer }
|
|
650
|
+
api_rate_limit_per_hour: { type: integer }
|
|
651
|
+
custom_pricing: { type: boolean }
|
|
652
|
+
|
|
653
|
+
Balance:
|
|
654
|
+
type: object
|
|
655
|
+
properties:
|
|
656
|
+
currency: { type: string, examples: ["USD"] }
|
|
657
|
+
available_balance: { type: number }
|
|
658
|
+
pending_balance: { type: number }
|
|
659
|
+
updated_at: { type: string, format: date-time }
|
|
660
|
+
|
|
661
|
+
Invoice:
|
|
662
|
+
type: object
|
|
663
|
+
properties:
|
|
664
|
+
transaction_id: { type: string, examples: ["STX-..."] }
|
|
665
|
+
purchase_type: { type: string, examples: ["plan_purchase", "topup"] }
|
|
666
|
+
amount_fiat: { type: number }
|
|
667
|
+
currency_fiat: { $ref: "#/components/schemas/FiatCurrency" }
|
|
668
|
+
status: { type: string }
|
|
669
|
+
crypto_symbol: { $ref: "#/components/schemas/CryptoSymbol" }
|
|
670
|
+
created_at: { type: string, format: date-time }
|
|
671
|
+
confirmed_at: { type: [string, "null"], format: date-time }
|
|
672
|
+
expires_at: { type: string, format: date-time }
|
|
673
|
+
|
|
674
|
+
Pagination:
|
|
675
|
+
type: object
|
|
676
|
+
required: [limit, offset, total]
|
|
677
|
+
properties:
|
|
678
|
+
limit: { type: integer }
|
|
679
|
+
offset: { type: integer }
|
|
680
|
+
total: { type: integer }
|
|
681
|
+
|
|
682
|
+
WebhookPayload:
|
|
683
|
+
type: object
|
|
684
|
+
description: >
|
|
685
|
+
Payment-event payload. AMOUNTS ARE STRINGS (e.g. "100.00", "0.00109462")
|
|
686
|
+
to preserve decimal precision — parse before arithmetic.
|
|
687
|
+
required: [event, timestamp, transaction_id, status]
|
|
688
|
+
properties:
|
|
689
|
+
event:
|
|
690
|
+
type: string
|
|
691
|
+
enum:
|
|
692
|
+
- payment.created
|
|
693
|
+
- payment.pending
|
|
694
|
+
- payment.completed
|
|
695
|
+
- payment.overpaid
|
|
696
|
+
- payment.partial
|
|
697
|
+
- payment.expired
|
|
698
|
+
- payment.failed
|
|
699
|
+
timestamp: { type: string, format: date-time }
|
|
700
|
+
transaction_id: { type: string }
|
|
701
|
+
status: { $ref: "#/components/schemas/TransactionStatus" }
|
|
702
|
+
currency_crypto: { $ref: "#/components/schemas/CryptoSymbol" }
|
|
703
|
+
currency_fiat: { $ref: "#/components/schemas/FiatCurrency" }
|
|
704
|
+
amount_fiat: { type: string, description: "Decimal string." }
|
|
705
|
+
amount_usd: { type: string, description: "Decimal string." }
|
|
706
|
+
amount_crypto: { type: string, description: "Decimal string." }
|
|
707
|
+
order_id: { type: [string, "null"] }
|
|
708
|
+
receipt_url: { type: [string, "null"], format: uri, description: "Present on completed/overpaid." }
|
|
709
|
+
metadata: { $ref: "#/components/schemas/Metadata" }
|
|
710
|
+
|
|
711
|
+
Error:
|
|
712
|
+
type: object
|
|
713
|
+
required: [success, error, message]
|
|
714
|
+
properties:
|
|
715
|
+
success: { const: false }
|
|
716
|
+
error: { type: string, description: "Machine-readable code.", examples: ["AMOUNT_TOO_LOW"] }
|
|
717
|
+
message: { type: string, description: "Human-readable description." }
|
|
718
|
+
|
|
719
|
+
headers:
|
|
720
|
+
X-RateLimit-Limit:
|
|
721
|
+
description: Requests allowed per minute for this API key's plan tier.
|
|
722
|
+
schema: { type: integer }
|
|
723
|
+
X-RateLimit-Remaining:
|
|
724
|
+
description: Requests remaining in the current one-minute window.
|
|
725
|
+
schema: { type: integer }
|
|
726
|
+
X-RateLimit-Reset:
|
|
727
|
+
description: Unix time (seconds) when the current rate-limit window resets.
|
|
728
|
+
schema: { type: integer, format: int64 }
|
|
729
|
+
Retry-After:
|
|
730
|
+
description: Seconds to wait before retrying (sent on 429 responses).
|
|
731
|
+
schema: { type: integer }
|
|
732
|
+
|
|
733
|
+
responses:
|
|
734
|
+
BadRequest:
|
|
735
|
+
description: Validation error (INVALID_REQUEST, INVALID_CRYPTO, INVALID_AMOUNT, AMOUNT_TOO_LOW, INVALID_CURRENCY, INVALID_METADATA, WALLET_NOT_CONFIGURED, MISSING_ITEMS, MISSING_ORDER_ID, …).
|
|
736
|
+
content:
|
|
737
|
+
application/json:
|
|
738
|
+
schema: { $ref: "#/components/schemas/Error" }
|
|
739
|
+
Unauthorized:
|
|
740
|
+
description: Missing or invalid API key (UNAUTHORIZED).
|
|
741
|
+
content:
|
|
742
|
+
application/json:
|
|
743
|
+
schema: { $ref: "#/components/schemas/Error" }
|
|
744
|
+
Forbidden:
|
|
745
|
+
description: Key lacks permission — e.g. a publishable key on a secret-only endpoint, or plan too low (FORBIDDEN, USE_PAY_ENDPOINT, PLAN_UPGRADE_REQUIRED, NO_ACTIVE_PLAN).
|
|
746
|
+
content:
|
|
747
|
+
application/json:
|
|
748
|
+
schema: { $ref: "#/components/schemas/Error" }
|
|
749
|
+
NotFound:
|
|
750
|
+
description: Resource not found (TRANSACTION_NOT_FOUND).
|
|
751
|
+
content:
|
|
752
|
+
application/json:
|
|
753
|
+
schema: { $ref: "#/components/schemas/Error" }
|
|
754
|
+
InsufficientBalance:
|
|
755
|
+
description: Merchant platform balance too low for overage fees (INSUFFICIENT_BALANCE).
|
|
756
|
+
content:
|
|
757
|
+
application/json:
|
|
758
|
+
schema: { $ref: "#/components/schemas/Error" }
|
|
759
|
+
ActiveTransactionExists:
|
|
760
|
+
description: This client IP already has an active transaction (ACTIVE_TRANSACTION_EXISTS). Body includes an `existing_transaction` object.
|
|
761
|
+
content:
|
|
762
|
+
application/json:
|
|
763
|
+
schema:
|
|
764
|
+
allOf:
|
|
765
|
+
- { $ref: "#/components/schemas/Error" }
|
|
766
|
+
- type: object
|
|
767
|
+
properties:
|
|
768
|
+
existing_transaction:
|
|
769
|
+
type: object
|
|
770
|
+
properties:
|
|
771
|
+
transaction_id: { type: string }
|
|
772
|
+
status: { $ref: "#/components/schemas/TransactionStatus" }
|
|
773
|
+
payment_url: { type: string, format: uri }
|
|
774
|
+
TooManyRequests:
|
|
775
|
+
description: >
|
|
776
|
+
Rate limit or quota exceeded. `error` is `RATE_LIMIT_EXCEEDED` (per-minute request
|
|
777
|
+
rate — honour `Retry-After`) or `MONTHLY_LIMIT_REACHED` (the plan's monthly
|
|
778
|
+
transaction quota). Rate-limit headers accompany the `RATE_LIMIT_EXCEEDED` case.
|
|
779
|
+
headers:
|
|
780
|
+
X-RateLimit-Limit: { $ref: "#/components/headers/X-RateLimit-Limit" }
|
|
781
|
+
X-RateLimit-Remaining: { $ref: "#/components/headers/X-RateLimit-Remaining" }
|
|
782
|
+
X-RateLimit-Reset: { $ref: "#/components/headers/X-RateLimit-Reset" }
|
|
783
|
+
Retry-After: { $ref: "#/components/headers/Retry-After" }
|
|
784
|
+
content:
|
|
785
|
+
application/json:
|
|
786
|
+
schema: { $ref: "#/components/schemas/Error" }
|
|
787
|
+
ServerError:
|
|
788
|
+
description: Internal error (RATE_FETCH_FAILED, ADDRESS_GENERATION_FAILED, UPSTREAM_ERROR, …).
|
|
789
|
+
content:
|
|
790
|
+
application/json:
|
|
791
|
+
schema: { $ref: "#/components/schemas/Error" }
|