{"openapi":"3.1.0","info":{"title":"Payg0 API","description":"\nAgent-native P2P payments in Mexican pesos (MXN). Guide for developers:\nhttps://payg0.io/developers · Instructions for AI agents: https://payg0.io/SKILL.md\n","version":"1.0.0"},"paths":{"/api/v1/auth/login":{"post":{"tags":["Auth"],"summary":"Login","description":"Logs in with email and password and returns a JWT for user sessions (24 hours).","operationId":"login_api_v1_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/me":{"get":{"tags":["Auth"],"summary":"Me","description":"Profile of the authenticated user.","operationId":"me_api_v1_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfile"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/wallet/balance":{"get":{"tags":["Wallet"],"summary":"Get Balance","description":"Total, held and available balance. Use `available_balance` as the money the user can send.","operationId":"get_balance_api_v1_wallet_balance_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletBalance"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/payments/intents":{"post":{"tags":["Payment intents"],"summary":"Create Payment Intent","description":"Proposes a payment that the user must confirm with their PIN at `confirm_url`.\n\n**No money moves.** Balance, limits and recipient are checked on confirmation.\nThe link expires after 10 minutes.","operationId":"create_payment_intent_api_v1_payments_intents_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentIntentCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentIntentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/payments/intents/{intent_id}":{"get":{"tags":["Payment intents"],"summary":"Get Payment Intent","description":"Status of a payment awaiting confirmation. Use it to know whether the user confirmed it.","operationId":"get_payment_intent_api_v1_payments_intents__intent_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"intent_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Intent Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentIntentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/payments/validate":{"post":{"tags":["Payments"],"summary":"Validate Payment","description":"Validates a payment WITHOUT running it. Useful to show a confirmation before charging.\nReturns the user's limits and whether the operation would be approved or rejected.","operationId":"validate_payment_api_v1_payments_validate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendPaymentRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/payments/send":{"post":{"tags":["Payments"],"summary":"Send Payment","description":"Sends a payment **without human confirmation**. Only for an API key with\n**automatic payments** turned on by its owner on payg0.io (with their PIN),\nwithin the key's caps (per payment and per day) and the tier limits. The API\nnever accepts a PIN.\n\nWithout automatic payments, create a payment intent (`POST /payments/intents`):\nthe user confirms it with their PIN on payg0.io.\n\n**Registered recipient:** the payment completes immediately (COMPLETED).\n**Unregistered recipient (email):** the payment stays PENDING until they sign up, for up to\nPENDING_PAYMENT_EXPIRY_DAYS days (3 by default); then it expires and the money returns to the sender.\n\nErrors: 403 `AUTOPAY_OFF` / `AUTOPAY_EXPIRED` / `PAYMENTS_ON_HOLD`; 422 `AUTOPAY_LIMIT_PAYMENT`,\n`AUTOPAY_LIMIT_DAILY`, `LIMIT_SINGLE_TX`, `LIMIT_BALANCE`, `LIMIT_MONTHLY`.\nEvery automatic payment is emailed to the key's owner.","operationId":"send_payment_api_v1_payments_send_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendPaymentRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/payments/history":{"get":{"tags":["Payments"],"summary":"Payment History","description":"Sent and received payments, newest first, filterable by status and dates.","operationId":"payment_history_api_v1_payments_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"from_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"From Date"}},{"name":"to_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"To Date"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/payments/{transaction_id}":{"get":{"tags":["Payments"],"summary":"Get Transaction","description":"One payment the user sent or received.","operationId":"get_transaction_api_v1_payments__transaction_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"transaction_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Transaction Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/payments/{transaction_id}/cancel":{"post":{"tags":["Payments"],"summary":"Cancel Transaction","description":"Cancels a PENDING payment (only the sender can).\nReverts the sender's monthly withdrawal counter.","operationId":"cancel_transaction_api_v1_payments__transaction_id__cancel_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"transaction_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Transaction Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/lookup":{"get":{"tags":["Users"],"summary":"Lookup User","description":"Finds a user by nickname or email. Returns the nickname and a masked display name (e.g. *Carlos L.*), never the full name.","operationId":"lookup_user_api_v1_users_lookup_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"title":"Q"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/developer-mode":{"patch":{"tags":["Users"],"summary":"Toggle Developer Mode","description":"Turns developer mode on or off (needed to create API keys and webhooks).","operationId":"toggle_developer_mode_api_v1_users_developer_mode_patch","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/me/pin":{"post":{"tags":["Users"],"summary":"Set Pin","description":"Sets up the payment PIN of an account without one. Requires the current password.","operationId":"set_pin_api_v1_users_me_pin_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinSetRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"tags":["Users"],"summary":"Delete Pin","description":"Removes the payment PIN. Requires the current password and the current PIN.","operationId":"delete_pin_api_v1_users_me_pin_delete","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinDeleteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["Users"],"summary":"Change Pin","description":"Changes the payment PIN. Requires the current PIN.","operationId":"change_pin_api_v1_users_me_pin_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinChangeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/me/pin/status":{"get":{"tags":["Users"],"summary":"Get Pin Status","description":"Whether the user has an active PIN and whether there is a lockout.","operationId":"get_pin_status_api_v1_users_me_pin_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/{user_id}/tier":{"get":{"tags":["Users"],"summary":"Get User Tier","description":"Returns the tier, limits and usage percentage for the current month.\nYou can only query your own tier.","operationId":"get_user_tier_api_v1_users__user_id__tier_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/keys":{"get":{"tags":["Developer"],"summary":"List Api Keys","description":"Lists the user's active API keys (prefix and name only).","operationId":"list_api_keys_api_v1_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/APIKeyResponse"},"type":"array","title":"Response List Api Keys Api V1 Keys Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["Developer"],"summary":"Create Api Key","description":"Creates an API key. The full key appears only in this response; store it.","operationId":"create_api_key_api_v1_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAPIKeyRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/APIKeyCreatedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/keys/{key_id}":{"delete":{"tags":["Developer"],"summary":"Delete Api Key","description":"Revokes an API key immediately.","operationId":"delete_api_key_api_v1_keys__key_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Key Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks":{"get":{"tags":["Developer"],"summary":"List Webhooks","description":"Lists active webhooks (without their secrets).","operationId":"list_webhooks_api_v1_webhooks_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/WebhookResponse"},"type":"array","title":"Response List Webhooks Api V1 Webhooks Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["Developer"],"summary":"Create Webhook","description":"Registers a webhook. Returns its `secret` only once; store it.","operationId":"create_webhook_api_v1_webhooks_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreatedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/webhooks/{webhook_id}":{"patch":{"tags":["Developer"],"summary":"Update Webhook","description":"Updates a webhook's URL and/or events without deleting and recreating it.","operationId":"update_webhook_api_v1_webhooks__webhook_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Webhook Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Developer"],"summary":"Delete Webhook","description":"Deletes a webhook.","operationId":"delete_webhook_api_v1_webhooks__webhook_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Webhook Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks/{webhook_id}/rotate-secret":{"post":{"tags":["Developer"],"summary":"Rotate Webhook Secret","description":"Generates a new secret for the webhook. The previous secret stops working\nimmediately. The new secret is returned only once; store it.","operationId":"rotate_webhook_secret_api_v1_webhooks__webhook_id__rotate_secret_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Webhook Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRotateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/usage":{"get":{"tags":["Developer"],"summary":"Get Usage","description":"API usage: total calls, broken down by key and by endpoint.","operationId":"get_usage_api_v1_usage_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^(hour|day|week|all)$","default":"day","title":"Period"}},{"name":"key_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Key Id"}},{"name":"endpoint","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"tags":["Health"],"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"APIKeyCreatedResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"key_prefix":{"type":"string","title":"Key Prefix"},"name":{"type":"string","title":"Name"},"is_active":{"type":"boolean","title":"Is Active"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"full_key":{"type":"string","title":"Full Key"}},"type":"object","required":["id","key_prefix","name","is_active","last_used_at","created_at","full_key"],"title":"APIKeyCreatedResponse"},"APIKeyResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"key_prefix":{"type":"string","title":"Key Prefix"},"name":{"type":"string","title":"Name"},"is_active":{"type":"boolean","title":"Is Active"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","key_prefix","name","is_active","last_used_at","created_at"],"title":"APIKeyResponse"},"CreateAPIKeyRequest":{"properties":{"name":{"type":"string","title":"Name"}},"type":"object","required":["name"],"title":"CreateAPIKeyRequest"},"CreateWebhookRequest":{"properties":{"url":{"type":"string","title":"Url"},"events":{"items":{"type":"string"},"type":"array","title":"Events"}},"type":"object","required":["url","events"],"title":"CreateWebhookRequest"},"EndpointStat":{"properties":{"endpoint":{"type":"string","title":"Endpoint"},"count":{"type":"integer","title":"Count"},"avg_response_ms":{"type":"number","title":"Avg Response Ms"}},"type":"object","required":["endpoint","count","avg_response_ms"],"title":"EndpointStat"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HourStat":{"properties":{"hour":{"type":"string","title":"Hour"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["hour","count"],"title":"HourStat"},"KeyStat":{"properties":{"key_prefix":{"type":"string","title":"Key Prefix"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["key_prefix","count"],"title":"KeyStat"},"LoginRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"password":{"type":"string","title":"Password"}},"type":"object","required":["email","password"],"title":"LoginRequest","description":"Authentication only: no strength validators (backwards compatibility)."},"PaymentIntentCreate":{"properties":{"recipient":{"type":"string","maxLength":255,"minLength":1,"title":"Recipient","description":"Nickname (@carlos or carlos) or email"},"amount":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*(?:\\d{0,14}|(?=[\\d.]{1,17}0*$)\\d{0,14}\\.\\d{0,2}0*$)"}],"title":"Amount"},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Description"}},"type":"object","required":["recipient","amount"],"title":"PaymentIntentCreate"},"PaymentIntentResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"type":"string","title":"Status","description":"AWAITING_CONFIRMATION | PROCESSING | CONFIRMED | DECLINED | EXPIRED | FAILED"},"recipient":{"type":"string","title":"Recipient"},"amount":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Amount"},"currency":{"type":"string","title":"Currency"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"confirm_url":{"type":"string","title":"Confirm Url","description":"Link the user opens to confirm the payment with their PIN."},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"transaction_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Transaction Id","description":"Transaction created on confirmation."},"failure_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Reason"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","status","recipient","amount","currency","description","confirm_url","expires_at","failure_reason","created_at"],"title":"PaymentIntentResponse"},"PinChangeRequest":{"properties":{"current_pin":{"type":"string","maxLength":6,"minLength":6,"title":"Current Pin"},"new_pin":{"type":"string","maxLength":6,"minLength":6,"title":"New Pin"}},"type":"object","required":["current_pin","new_pin"],"title":"PinChangeRequest"},"PinDeleteRequest":{"properties":{"password":{"type":"string","title":"Password","description":"Current password, to confirm removing the PIN"},"current_pin":{"type":"string","maxLength":6,"minLength":6,"title":"Current Pin","description":"Current payment PIN"}},"type":"object","required":["password","current_pin"],"title":"PinDeleteRequest"},"PinSetRequest":{"properties":{"pin":{"type":"string","maxLength":6,"minLength":6,"title":"Pin","description":"6-digit numeric PIN"},"password":{"type":"string","title":"Password","description":"Current password, to confirm your identity"}},"type":"object","required":["pin","password"],"title":"PinSetRequest"},"SendPaymentRequest":{"properties":{"recipient":{"type":"string","title":"Recipient","description":"Nickname (@carlos or carlos) or email address"},"amount":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"}],"title":"Amount"},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Description"}},"type":"object","required":["recipient","amount"],"title":"SendPaymentRequest"},"TokenResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"},"expires_in":{"type":"integer","title":"Expires In","default":86400}},"type":"object","required":["access_token"],"title":"TokenResponse"},"TransactionListResponse":{"properties":{"transactions":{"items":{"$ref":"#/components/schemas/TransactionResponse"},"type":"array","title":"Transactions"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"limit":{"type":"integer","title":"Limit"}},"type":"object","required":["transactions","total","page","limit"],"title":"TransactionListResponse"},"TransactionResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"sender_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Sender Id"},"receiver_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Receiver Id"},"receiver_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receiver Email"},"amount":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Amount"},"currency":{"type":"string","title":"Currency"},"status":{"type":"string","title":"Status"},"reason":{"type":"string","title":"Reason"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"sender_nickname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Nickname"},"receiver_nickname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receiver Nickname"}},"type":"object","required":["id","sender_id","receiver_id","receiver_email","amount","currency","status","reason","description","expires_at","created_at","updated_at"],"title":"TransactionResponse"},"UpdateWebhookRequest":{"properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"events":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Events"}},"type":"object","title":"UpdateWebhookRequest"},"UsageResponse":{"properties":{"period":{"type":"string","title":"Period"},"total_requests":{"type":"integer","title":"Total Requests"},"by_endpoint":{"items":{"$ref":"#/components/schemas/EndpointStat"},"type":"array","title":"By Endpoint"},"by_hour":{"items":{"$ref":"#/components/schemas/HourStat"},"type":"array","title":"By Hour"},"by_key":{"items":{"$ref":"#/components/schemas/KeyStat"},"type":"array","title":"By Key"}},"type":"object","required":["period","total_requests","by_endpoint","by_hour","by_key"],"title":"UsageResponse"},"UserProfile":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"nickname":{"type":"string","title":"Nickname"},"full_name":{"type":"string","title":"Full Name"},"is_active":{"type":"boolean","title":"Is Active"},"is_developer":{"type":"boolean","title":"Is Developer"},"is_admin":{"type":"boolean","title":"Is Admin"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","email","nickname","full_name","is_active","is_developer","is_admin","created_at","updated_at"],"title":"UserProfile"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WalletBalance":{"properties":{"balance":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Balance","description":"Total wallet balance, including funds held in escrow."},"held_balance":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Held Balance","description":"Funds in escrow: reserved by PENDING payments. Not available for new payments."},"available_balance":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Available Balance","description":"Funds available to send = balance − held_balance."},"currency":{"type":"string","title":"Currency","description":"Currency (always 'MXN' in this phase)."},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["balance","held_balance","available_balance","currency","updated_at"],"title":"WalletBalance","description":"The user's wallet balance.\n\n## Accounting model\n\n| Field              | Description                                                    |\n|--------------------|----------------------------------------------------------------|\n| `balance`          | Total balance (including funds in escrow)                      |\n| `held_balance`     | Funds held by **PENDING** payments (in escrow)                 |\n| `available_balance`| Funds available for new payments = `balance − held_balance`    |\n\n### Payment lifecycle\n\n- **PENDING** → only `held_balance += amount` (the total balance does not change)\n- **COMPLETED / CLAIM** → `sender.balance -= amount`, `receiver.balance += amount`, `sender.held_balance -= amount`\n- **CANCELLED / EXPIRED** → only `held_balance -= amount` (the total balance does not change)"},"WebhookCreatedResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"url":{"type":"string","title":"Url"},"events":{"items":{"type":"string"},"type":"array","title":"Events"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"secret":{"type":"string","title":"Secret"}},"type":"object","required":["id","url","events","is_active","created_at","secret"],"title":"WebhookCreatedResponse","description":"Response only on create or rotate; includes the secret exactly once."},"WebhookResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"url":{"type":"string","title":"Url"},"events":{"items":{"type":"string"},"type":"array","title":"Events"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","url","events","is_active","created_at"],"title":"WebhookResponse","description":"Standard response, without the secret (for listings)."},"WebhookRotateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"secret":{"type":"string","title":"Secret"}},"type":"object","required":["id","secret"],"title":"WebhookRotateResponse","description":"rotate-secret response: only the new secret."}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}},"tags":[{"name":"Auth","description":"Login and profile. Accounts cannot be created through the API: sign up at payg0.io/register."},{"name":"Wallet","description":"Balance"},{"name":"Payment intents","description":"Payments the user confirms with their PIN on payg0.io (recommended for agents)"},{"name":"Payments","description":"Sending and managing P2P payments"},{"name":"Users","description":"User lookup and settings"},{"name":"Developer","description":"API keys, webhooks and usage metrics"}]}