Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions api-tests/Addresses/Create Address.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
meta {
name: Create Address
type: http
seq: 1
}

post {
url: {{base_url}}/v1/wallets/{{wallet_id}}/addresses
body: json
auth: none
}

headers {
authorization: Bearer {{token}}
}

body:json {
{
"customer_ref": "test-customer-1",
"metadata": { "plan": "pro" }
}
}

script:post-response {
if (res.body?.data?.id) {
bru.setVar("address_id", res.body.data.id);
}
}

docs {
Generates a dedicated deposit address (muxed M... plus a G...+memo fallback) instantly,
off-chain. Both forms credit the same master wallet — there's nothing to sweep.
}
14 changes: 14 additions & 0 deletions api-tests/Addresses/List Addresses.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
meta {
name: List Addresses
type: http
seq: 2
}

get {
url: {{base_url}}/v1/wallets/{{wallet_id}}/addresses
auth: none
}

headers {
authorization: Bearer {{token}}
}
29 changes: 29 additions & 0 deletions api-tests/Auth/Login.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
meta {
name: Login
type: http
seq: 2
}

post {
url: {{base_url}}/v1/auth/login
body: json
auth: none
}

body:json {
{
"email": "your-existing-user@octo.test",
"password": "supersecret123"
}
}

script:post-response {
if (res.body?.data?.token) {
bru.setVar("token", res.body.data.token);
}
}

docs {
Log in an existing user. Edit the email/password to match a real account, or just re-run
Signup instead if you don't need a persistent one.
}
18 changes: 18 additions & 0 deletions api-tests/Auth/Logout.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
meta {
name: Logout
type: http
seq: 5
}

post {
url: {{base_url}}/v1/auth/logout
auth: none
}

headers {
authorization: Bearer {{token}}
}

docs {
Revokes the current token. Every other request will 401 until you Signup/Login again.
}
18 changes: 18 additions & 0 deletions api-tests/Auth/Me.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
meta {
name: Me
type: http
seq: 3
}

get {
url: {{base_url}}/v1/auth/me
auth: none
}

headers {
authorization: Bearer {{token}}
}

docs {
Returns the authenticated user. Confirms the token from Signup/Login is still valid.
}
24 changes: 24 additions & 0 deletions api-tests/Auth/Refresh.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
meta {
name: Refresh
type: http
seq: 4
}

post {
url: {{base_url}}/v1/auth/refresh
auth: none
}

headers {
authorization: Bearer {{token}}
}

script:post-response {
if (res.body?.data?.token) {
bru.setVar("token", res.body.data.token);
}
}

docs {
Issues a fresh token for an already-valid session and auto-saves it, replacing the old one.
}
33 changes: 33 additions & 0 deletions api-tests/Auth/Signup.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
meta {
name: Signup
type: http
seq: 1
}

post {
url: {{base_url}}/v1/auth/signup
body: json
auth: none
}

body:json {
{
"email": "test-{{$randomInt}}@octo.test",
"password": "supersecret123"
}
}

script:post-response {
if (res.body?.data?.token) {
bru.setVar("token", res.body.data.token);
bru.setVar("user_id", res.body.data.user.id);
}
}

docs {
Creates a dashboard user and returns a bearer token. The token is auto-saved to the
`token` variable so every other request in this collection can reuse it via
`Authorization: Bearer {{token}}`.

Re-run this any time you need a fresh user — each run generates a unique email.
}
42 changes: 42 additions & 0 deletions api-tests/Payment Links/Create Payment Link.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
meta {
name: Create Payment Link
type: http
seq: 1
}

post {
url: {{base_url}}/v1/wallets/{{wallet_id}}/payment-links
body: json
auth: none
}

headers {
authorization: Bearer {{token}}
}

body:json {
{
"name": "Test payment link",
"description": "Created from Bruno",
"amount_usdc_stroops": 10000000,
"redirect_url": "https://example.com/thank-you"
}
}

script:post-response {
if (res.body?.data?.slug) {
bru.setVar("link_id", res.body.data.id);
bru.setVar("link_slug", res.body.data.slug);
bru.setVar("checkout_url", res.body.data.url);
}
}

docs {
amount_usdc_stroops is optional — omit it for a flexible-amount link the payer fills in.
redirect_url is optional too — where the payer's browser goes after a confirmed payment.

The response's `url` field is the real hosted checkout link — open checkout_url in a browser
after running this to see the actual pay page. It's built from PUBLIC_APP_URL on the server,
so if it ever shows localhost in production, that env var isn't set correctly on the backend
host.
}
25 changes: 25 additions & 0 deletions api-tests/Payment Links/Deactivate Payment Link.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
meta {
name: Deactivate Payment Link
type: http
seq: 4
}

put {
url: {{base_url}}/v1/wallets/{{wallet_id}}/payment-links/{{link_id}}
body: json
auth: none
}

headers {
authorization: Bearer {{token}}
}

body:json {
{
"active": false
}
}

docs {
Set active: true to reactivate. An inactive link's public page (GET /v1/pay/:slug) 404s.
}
18 changes: 18 additions & 0 deletions api-tests/Payment Links/Get Payment Link.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
meta {
name: Get Payment Link
type: http
seq: 3
}

get {
url: {{base_url}}/v1/wallets/{{wallet_id}}/payment-links/{{link_id}}
auth: none
}

headers {
authorization: Bearer {{token}}
}

docs {
link_id is auto-saved by Create Payment Link.
}
14 changes: 14 additions & 0 deletions api-tests/Payment Links/List Payment Links.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
meta {
name: List Payment Links
type: http
seq: 2
}

get {
url: {{base_url}}/v1/wallets/{{wallet_id}}/payment-links
auth: none
}

headers {
authorization: Bearer {{token}}
}
19 changes: 19 additions & 0 deletions api-tests/Payment Links/List Payments (owner).bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
meta {
name: List Payments (owner)
type: http
seq: 5
}

get {
url: {{base_url}}/v1/wallets/{{wallet_id}}/payment-links/{{link_id}}/payments
auth: none
}

headers {
authorization: Bearer {{token}}
}

docs {
Owner-only: includes payer name/email, unlike anything on the public side. Includes pending
intents too, not just confirmed payments, so you can see abandoned checkouts.
}
30 changes: 30 additions & 0 deletions api-tests/Payment Links/Public - Create Intent.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
meta {
name: Public - Create Intent
type: http
seq: 7
}

post {
url: {{base_url}}/v1/pay/{{link_slug}}/intent
body: json
auth: none
}

body:json {
{
"payer_name": "Jane Doe",
"payer_email": "jane@example.com"
}
}

script:post-response {
if (res.body?.data?.payment_id) {
bru.setVar("payment_id", res.body.data.payment_id);
}
}

docs {
No auth, rate-limited by IP (5/min). Allocates a dedicated address for THIS payment — two
concurrent payers on the same link get different addresses, so a deposit can only ever match
one of them. amount_usdc_stroops is required here only if the link itself is flexible-amount.
}
15 changes: 15 additions & 0 deletions api-tests/Payment Links/Public - Get Link.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
meta {
name: Public - Get Link
type: http
seq: 6
}

get {
url: {{base_url}}/v1/pay/{{link_slug}}
auth: none
}

docs {
No auth — this is what the hosted checkout page calls first. Returns the link's public
details plus the deposit address to send USDC to.
}
16 changes: 16 additions & 0 deletions api-tests/Payment Links/Public - Get Payment Status.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
meta {
name: Public - Get Payment Status
type: http
seq: 8
}

get {
url: {{base_url}}/v1/pay/{{link_slug}}/payments/{{payment_id}}
auth: none
}

docs {
No auth. status is one of pending | confirmed | expired | underpaid | overpaid. The pay page
polls this every ~3s while waiting. expected_usdc_stroops/received_usdc_stroops let you show
a mismatch banner without a second request.
}
19 changes: 19 additions & 0 deletions api-tests/Payment Links/Public - Get Signing Info.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
meta {
name: Public - Get Signing Info
type: http
seq: 9
}

get {
url: {{base_url}}/v1/pay/{{link_slug}}/signing-info?account={{payer_account}}
auth: none
}

docs {
No auth. account should be the PAYER's own Stellar address (e.g. from Freighter) — this
returns THAT account's current sequence number, network passphrase, and base fee, everything
needed to build a transaction client-side without hitting Horizon directly.

Set the payer_account variable to a real G... address to try this (e.g. the one printed by
sign-challenge.js, once funded).
}
Loading
Loading