Keter Bank Keter Bank API REFERENCE
← Login

Keter Bank API Reference

A REST API for the Keter Bank Minecraft economy. Build integrations, automate transactions, and add "Login with Keter" to your own sites.

https://mc.bank.jacksampson.lol/api
FormatJSON (application/json)
AuthJWT or API key
CORSEnabled on all endpoints
Version3.0

Error Format

All endpoints return a consistent JSON envelope. Check success before reading other fields.

All responses include a success boolean. On failure, a message or error field describes what went wrong.
{
  "success": false,
  "message": "Insufficient funds",
  "error_code": "INSUFFICIENT_FUNDS"  // where available
}

HTTP StatusMeaning
200Success (check success: true)
400Bad request — missing or invalid parameters
401Unauthorized — wrong credentials or expired token
403Forbidden — account inactive or insufficient permissions
404Not found — account, card, or resource does not exist
409Conflict — duplicate request or state mismatch

JWT Authentication

Protected endpoints require a signed JWT passed in the Authorization header.

How it works: Call /api/business-login to receive a token (JWT). Pass it as a Bearer token on all subsequent requests that require authentication.
// Include on every protected request:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Token typeIssued byLifetimeUsed for
Business JWT/api/business-login2 hoursBusiness endpoints and registering OAuth apps
API KeyBusiness dashboardUntil revokedServer-to-server: card charges and transfers
OAuth Access Token/api/oauth/token1 hourThird-party apps reading user info via OAuth

Registration

Apply for a Keter Bank account. Once submitted, your application is reviewed by an admin.

POST /api/request-account
Submit an account application. Requires admin approval before the account becomes active.
Public
Applications are reviewed by an admin. Once approved, the player will be able to log in immediately.
Request Body
FieldTypeRequiredDescription
usernamestringRequired3–16 chars, alphanumeric and underscores only
minecraft_uuidstringRequiredStandard UUID format (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
passwordstringRequiredMinimum 6 characters
emailstringOptionalContact email address
Response — 201 Created
{
  "success": true,
  "message": "Account request submitted! Please wait for admin approval."
}

Cards

Process card payments as a business merchant.

POST /api/charge-card
Process a direct card charge as a business merchant. A 2.5% + $0.10 processing fee is deducted from the settlement.
API Key
Requires a valid business API key in the X-API-Key header.
Request Body
FieldTypeRequiredDescription
merchant_business_idstringRequiredYour business account ID
card_numberstringRequiredFull 16-digit card number
cvvstringRequired3-digit CVV
amountnumberRequiredCharge amount
customer_namestringOptionalCardholder name for records
Response — 200 OK (always 200; check authorized)
{
  "success": true,
  "authorized": true,
  "authorization_code": "CHRG-XYZ789",
  "amount": 50.00,
  "merchant_fee": 1.35,  // 2.5% + $0.10
  "net_amount": 48.65
}

// Declined:
{
  "success": true,
  "authorized": false,
  "decline_reason": "Insufficient funds"
}

Business Banking

Open and manage business accounts, issue API keys, and process card payments on behalf of your business.

POST /api/business-account
Open a new business bank account. Requires an initial deposit from a personal account.
Public
Request Body
FieldTypeRequiredDescription
business_namestringRequiredLegal business name
account_typestringRequiredBusiness account type
einstringRequiredEmployer identification number
industrystringRequiredBusiness industry
ownersarrayRequiredArray of owner objects: { uuid, name, role, password }
initial_depositnumberRequiredOpening deposit (minimum $100)
funding_account_uuidstringOptionalPersonal account UUID to fund the opening deposit
dba_namestringOptionalDoing-business-as name
descriptionstringOptionalBusiness description
Response — 200 OK
{
  "success": true,
  "business_id": "biz_abc123",
  "account_number": "987654321098",
  "business_name": "Creeper's Craft Shop",
  "initial_balance": 500.00,
  "owners_count": 1
}
POST /api/business-login
Authenticate as an owner or admin of a business account. Returns a JWT for business endpoints.
Public
Request Body
FieldTypeRequiredDescription
business_idstringRequiredBusiness UUID or account number
user_uuidstringRequiredAuthorized user's Minecraft UUID
passwordstringOptionalRequired if account has a password set
Response — 200 OK
{
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiJ9...",  // Business JWT
  "business_id": "biz_abc123",
  "business_name": "Creeper's Craft Shop",
  "account_number": "987654321098",
  "user_name": "Steve",
  "role": "OWNER",
  "permissions": {
    "can_view": true,
    "can_transact": true,
    "can_manage_users": true,
    "can_charge_cards": true
  }
}
POST /api/business-transfer
Transfer funds from a business account to a personal account. Authenticated via API key in the request header.
API Key
Pass your API key as X-API-Key in the request header.
Request Headers
HeaderRequiredDescription
X-API-KeyRequiredYour business API key (kb_live_…)
Request Body
FieldTypeRequiredDescription
to_account_numberstringRequired12-digit recipient personal account number
amountnumberRequiredTransfer amount
descriptionstringOptionalMemo / transfer reason
referencestringOptionalYour internal reference ID
Response — 200 OK
{
  "success": true,
  "message": "Transfer successful",
  "transaction_id": "txn_biz_456",
  "amount": 250.00,
  "from_business": "Creeper's Craft Shop",
  "to_account": "123456789012",
  "timestamp": "2024-12-15T14:32:00Z"
}

Login with Keter

An OAuth 2.0 authorization_code flow that lets your site authenticate Keter Bank users and read their account data with their consent.

Quick start: Register your app as a business → get a client_id and client_secret → redirect users to the consent page → exchange the code for a token → call userinfo.

The flow in 4 steps

1
Register your app
Call POST /api/oauth/register with your Business JWT. You receive a client_id and client_secret — store the secret securely, it's shown once.
2
Redirect the user to the consent screen
Send users to /oauth/authorize?client_id=…&redirect_uri=…&scope=…&state=…. They log in (if not already) and approve or deny the request.
3
Exchange the authorization code for a token
Keter redirects back to your redirect_uri with ?code=…&state=…. Your server calls POST /api/oauth/token to exchange the code for an access token.
4
Fetch user data
Call GET /api/oauth/userinfo with the access token as Authorization: Bearer <token>. Receive only the scopes the user approved.

Available scopes

Scope
Fields returned
Description
profile
username
Keter username
minecraft_uuid
minecraft_uuid
Player's Minecraft UUID
balance
balance
Available account balance
account_number
account_number
12-digit bank account number
POST /api/oauth/register
Register a new "Login with Keter" app for your business. Returns a client_id and client_secret shown once.
Business JWTOAuth
Secret shown once. Store your client_secret immediately — it is hashed on our end and cannot be retrieved again. If lost, delete and re-register your app.
Request Body
FieldTypeRequiredDescription
app_namestringRequiredDisplay name shown on the consent screen (min 2 chars)
redirect_urisstring[]RequiredAllowed callback URLs. Must be HTTPS (localhost/127.0.0.1 exempt)
scopesstring[]RequiredScopes your app needs: profile, minecraft_uuid, balance, account_number
Example Request
{
  "app_name": "My Plugin Store",
  "redirect_uris": ["https://mypluginstore.com/oauth/callback"],
  "scopes": ["profile", "minecraft_uuid"]
}
Response — 200 OK
{
  "success": true,
  "client_id": "keter_a1b2c3d4e5f6a1b2c3d4e5f6",
  "client_secret": "8f14e45f...",  // shown ONCE — store it now
  "message": "Store your client_secret now — it cannot be retrieved again."
}
GET /api/oauth/app-info
Fetch public information about an OAuth app. Used internally by the consent screen.
PublicOAuth
Query Parameters
ParameterTypeRequired
client_idstringRequired
Response — 200 OK
{
  "success": true,
  "app_name": "My Plugin Store",
  "business_name": "Creeper's Craft Shop",
  "allowed_scopes": ["profile", "minecraft_uuid"]
}
POST /api/oauth/authorize
Called by the consent screen after the user approves the request. Generates a short-lived authorization code.
Personal JWTOAuth
You don't call this directly — the consent page at /oauth/authorize handles it. The user is redirected here automatically after approving.
Consent screen URL
GET /oauth/authorize
  ?client_id=keter_a1b2c3d4e5f6…
  &redirect_uri=https://yoursite.com/callback
  &scope=profile%20minecraft_uuid
  &state=random_csrf_token
Request Body (sent by consent page)
FieldTypeRequiredDescription
client_idstringRequiredYour app's client ID
redirect_uristringRequiredMust exactly match a registered redirect URI
scopestringRequiredSpace-separated scopes (subset of what was registered)
statestringOptionalRandom value to prevent CSRF — echoed back in the redirect
Success — redirects to your callback
https://yoursite.com/callback?code=abc123…&state=your_state

// Code expires in 10 minutes and is single-use
Denial — redirects with error
https://yoursite.com/callback?error=access_denied&state=your_state
POST /api/oauth/token
Exchange an authorization code for an access token. Server-to-server — never expose your client_secret in the browser.
OAuth
Keep your secret server-side. This endpoint should only be called from your backend. Never send client_secret from a browser.
Request Body
FieldTypeRequiredDescription
grant_typestringRequiredMust be "authorization_code"
codestringRequiredThe authorization code from the redirect
client_idstringRequiredYour app's client ID
client_secretstringRequiredYour app's client secret
redirect_uristringRequiredMust match the URI used during authorization
Response — 200 OK
{
  "access_token": "8f14e45fceea167a5a36dedd4b...",
  "token_type": "Bearer",
  "expires_in": 3600,  // seconds
  "scope": "profile minecraft_uuid"
}
GET /api/oauth/userinfo
Return the scoped profile data for the authenticated user. Only fields covered by the granted scopes are included.
OAuth Access Token
Request Headers
HeaderRequiredDescription
AuthorizationRequiredBearer <access_token>
Response — 200 OK
{
  "sub": "player-uuid-here",         // always present

  // scope: profile
  "username": "Steve",

  // scope: minecraft_uuid
  "minecraft_uuid": "550e8400-e29b-41d4-a716-446655440000",

  // scope: balance
  "balance": 1250.00,

  // scope: account_number
  "account_number": "123456789012"
}