{"openapi":"3.1.0","info":{"title":"Bitcrowd Pay Merchant API","version":"1.0.0","description":"Server-side merchant payment, hosted Payment Link, and waitlist operations. Owner management and internal operations are not part of this public contract."},"servers":[{"url":"https://api.example.test","description":"Replace with the approved Bitcrowd Pay API host"}],"tags":[{"name":"Merchant payments"},{"name":"Public payment links"},{"name":"Public waitlist"}],"paths":{"/api/v1/payments/stk":{"post":{"operationId":"createStkPayment","tags":["Merchant payments"],"summary":"Initiate an M-PESA STK Push","description":"Create one server-side Sandbox or approved Live STK Push. Treat the 202 response as accepted/pending, retain the same Idempotency-Key for retries, and reconcile ambiguous outcomes through the payment status endpoint.","security":[{"merchantApiKey":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePayment"},"example":{"phone_number":"2547XXXXXXX","amount":1,"external_reference":"postman-sandbox-001","metadata":{"source":"postman"}}}}},"responses":{"202":{"$ref":"#/components/responses/Payment"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"413":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}},"/api/v1/payments":{"get":{"operationId":"listMerchantPayments","tags":["Merchant payments"],"summary":"Search payments","description":"List payments for the authenticated merchant channel using cursor pagination. Results are ordered newest first; follow next_cursor until it is null.","security":[{"merchantApiKey":[]}],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"status","in":"query","schema":{"$ref":"#/components/schemas/PaymentStatus"}},{"name":"reference","in":"query","schema":{"type":"string","maxLength":100}},{"name":"created_from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"created_to","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"$ref":"#/components/responses/PaymentList"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/payments/{payment_id}":{"get":{"operationId":"getMerchantPayment","tags":["Merchant payments"],"summary":"Get a payment","description":"Retrieve the current status and provider evidence for one payment visible to the authenticated merchant channel.","security":[{"merchantApiKey":[]}],"parameters":[{"$ref":"#/components/parameters/PaymentId"}],"responses":{"200":{"$ref":"#/components/responses/Payment"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/public/v1/payment-links/{slug}":{"get":{"operationId":"getPublicPaymentLink","tags":["Public payment links"],"summary":"Resolve an active hosted payment link","description":"Resolve the customer-safe configuration for an active hosted Payment Link. The response does not expose owner credentials or internal routing identifiers.","parameters":[{"$ref":"#/components/parameters/PaymentLinkSlug"}],"responses":{"200":{"$ref":"#/components/responses/CustomerPaymentLink"},"404":{"$ref":"#/components/responses/Error"},"410":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/public/v1/payment-links/{slug}/payments/stk":{"post":{"operationId":"createPaymentLinkStkPayment","tags":["Public payment links"],"summary":"Initiate an STK Push from an active payment link","description":"Start one customer payment through an active hosted Payment Link. Treat 202 as accepted/pending and keep the same Idempotency-Key for one logical attempt.","parameters":[{"$ref":"#/components/parameters/PaymentLinkSlug"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentLinkCheckout"}}}},"responses":{"202":{"$ref":"#/components/responses/Payment"},"400":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"410":{"$ref":"#/components/responses/Error"},"413":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}},"/api/public/v1/payment-links/{slug}/payments/{payment_id}":{"get":{"operationId":"getPaymentLinkPayment","tags":["Public payment links"],"summary":"Poll a payment created through a hosted link","description":"Poll the current status of a payment created through this hosted Payment Link. Continue until the payment reaches a terminal status.","parameters":[{"$ref":"#/components/parameters/PaymentLinkSlug"},{"$ref":"#/components/parameters/PaymentId"}],"responses":{"200":{"$ref":"#/components/responses/Payment"},"404":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/public/v1/waitlist":{"post":{"operationId":"joinPublicWaitlist","tags":["Public waitlist"],"summary":"Submit a coming-soon waitlist request","description":"This is not account creation or product access. New and existing normalized email addresses receive the same generic response.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistSubmission"},"example":{"email":"person@example.com","name":"Example Person","company":"Example Co","use_case":"Collect product payments","consent":true,"source":"landing","campaign":"launch-2026","website":"","form_started_at":"{{current_unix_ms}}"}}}},"responses":{"202":{"description":"Generic waitlist acknowledgement; does not disclose membership","headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistAccepted"}}}},"400":{"$ref":"#/components/responses/Error"},"413":{"$ref":"#/components/responses/Error"},"415":{"$ref":"#/components/responses/Error"},"429":{"description":"Waitlist rate limit exceeded","headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}},"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds until another submission may be attempted."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}}},"components":{"schemas":{"CreatePayment":{"type":"object","additionalProperties":false,"required":["phone_number","amount","external_reference"],"properties":{"phone_number":{"type":"string"},"amount":{"type":"integer","minimum":1},"external_reference":{"type":"string","minLength":1,"maxLength":100},"metadata":{"type":"object","description":"Maximum serialized size: 8 KiB","additionalProperties":true}}},"PaymentStatus":{"type":"string","enum":["CREATED","PENDING","SUCCESS","FAILED","CANCELLED","TIMED_OUT"]},"PaymentLinkCheckout":{"type":"object","required":["phone_number","amount"],"properties":{"phone_number":{"type":"string"},"amount":{"type":"integer","minimum":1},"external_reference":{"type":"string","maxLength":100},"metadata":{"type":"object","additionalProperties":true},"payer_name":{"type":"string","maxLength":120},"payer_email":{"type":"string","format":"email"}}},"WaitlistSubmission":{"type":"object","additionalProperties":false,"required":["email","consent","form_started_at"],"properties":{"email":{"type":"string","format":"email","maxLength":254},"name":{"type":"string","maxLength":100},"company":{"type":"string","maxLength":120},"use_case":{"type":"string","maxLength":500},"consent":{"const":true,"description":"Acknowledges the waitlist privacy/communications notice."},"source":{"type":"string","enum":["landing","docs","referral","other"],"default":"landing"},"campaign":{"type":"string","pattern":"^[a-z0-9][a-z0-9_-]{0,63}$"},"website":{"type":"string","maxLength":200,"description":"Honeypot field; leave empty."},"form_started_at":{"type":"integer","format":"int64","description":"Client form start time in Unix milliseconds."}}},"WaitlistAccepted":{"type":"object","required":["success","status","message","customerMessage","data","timestamp"],"properties":{"success":{"const":true},"status":{"const":"success"},"message":{"type":"string"},"customerMessage":{"type":"string"},"data":{"type":"object","required":["received"],"properties":{"received":{"const":true}}},"timestamp":{"type":"string","format":"date-time"}}},"Error":{"type":"object","required":["success","status","message","customerMessage","error","timestamp"],"properties":{"success":{"const":false},"status":{"const":"error"},"message":{"type":"string"},"customerMessage":{"type":"string"},"error":{"type":"object","required":["code"],"properties":{"code":{"type":"string"},"details":{"type":"object","additionalProperties":true}}},"timestamp":{"type":"string","format":"date-time"}}},"CustomerPaymentLink":{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string","enum":["GENERAL","DEDICATED"]},"slug":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["ACTIVE","PAUSED","ARCHIVED"]},"amountMode":{"$ref":"#/components/schemas/PaymentLinkAmountMode"},"fixedAmount":{"type":["integer","null"]},"presetAmounts":{"type":"array","items":{"type":"integer"}},"minimumAmount":{"type":["integer","null"]},"maximumAmount":{"type":["integer","null"]},"referenceMode":{"$ref":"#/components/schemas/PaymentLinkReferenceMode"},"collectPayerName":{"type":"boolean"},"collectPayerEmail":{"type":"boolean"},"successMessage":{"type":["string","null"]},"successRedirectUrl":{"type":["string","null"],"format":"uri"},"startsAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"maxSuccessfulUses":{"type":["integer","null"]},"successfulUses":{"type":"integer"},"receivingAccount":{"type":["object","null"],"properties":{"name":{"type":"string"},"type":{"type":"string"}}},"channel":{"type":"object","properties":{"name":{"type":"string"},"environment":{"$ref":"#/components/schemas/Environment"},"destinationName":{"type":"string"},"destinationType":{"type":"string"}}}}},"PaymentLinkAmountMode":{"type":"string","enum":["FIXED","CUSTOMER_ENTERED","PRESETS"]},"PaymentLinkReferenceMode":{"type":"string","enum":["FIXED","REQUIRED","OPTIONAL","GENERATED"]},"Environment":{"type":"string","enum":["SANDBOX","LIVE"]},"PaymentList":{"type":"object","required":["payments","next_cursor"],"properties":{"payments":{"type":"array","items":{"$ref":"#/components/schemas/Payment"}},"next_cursor":{"type":["string","null"]}}},"Payment":{"type":"object","required":["payment_id","payment_status","amount","currency","phone_number","external_reference","metadata","merchant_request_id","checkout_request_id","mpesa_receipt_number","result_code","result_description","created_at","initiated_at","completed_at"],"properties":{"payment_id":{"type":"string","pattern":"^pay_"},"payment_status":{"$ref":"#/components/schemas/PaymentStatus"},"amount":{"type":"integer","minimum":1},"currency":{"type":"string","const":"KES"},"phone_number":{"type":"string","description":"Masked in public responses (for example 2547******5678)."},"external_reference":{"type":"string"},"metadata":{"type":["object","null"],"additionalProperties":true},"merchant_request_id":{"type":["string","null"]},"checkout_request_id":{"type":["string","null"]},"mpesa_receipt_number":{"type":["string","null"]},"result_code":{"type":["integer","null"]},"result_description":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"initiated_at":{"type":["string","null"],"format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"}}}},"responses":{"Payment":{"description":"Payment response envelope","content":{"application/json":{"schema":{"type":"object","required":["success","status","message","customerMessage","data","timestamp"],"properties":{"success":{"const":true},"status":{"const":"success"},"message":{"type":"string"},"customerMessage":{"type":"string"},"data":{"$ref":"#/components/schemas/Payment"},"timestamp":{"type":"string","format":"date-time"}}}}}},"Error":{"description":"Structured API error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PaymentList":{"description":"Paginated payment list response envelope","content":{"application/json":{"schema":{"type":"object","required":["success","status","message","customerMessage","data","timestamp"],"properties":{"success":{"const":true},"status":{"const":"success"},"message":{"type":"string"},"customerMessage":{"type":"string"},"data":{"$ref":"#/components/schemas/PaymentList"},"timestamp":{"type":"string","format":"date-time"}}}}}},"CustomerPaymentLink":{"description":"Customer-safe hosted Payment Link response envelope","content":{"application/json":{"schema":{"type":"object","required":["success","status","message","customerMessage","data","timestamp"],"properties":{"success":{"const":true},"status":{"const":"success"},"message":{"type":"string"},"customerMessage":{"type":"string"},"data":{"$ref":"#/components/schemas/CustomerPaymentLink"},"timestamp":{"type":"string","format":"date-time"}}}}}}},"parameters":{"Limit":{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},"Cursor":{"name":"cursor","in":"query","schema":{"type":"string"}},"PaymentId":{"name":"payment_id","in":"path","required":true,"schema":{"type":"string","pattern":"^pay_"}},"PaymentLinkSlug":{"name":"slug","in":"path","required":true,"schema":{"type":"string","minLength":3,"maxLength":120}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":200}}},"securitySchemes":{"merchantApiKey":{"type":"http","scheme":"bearer","bearerFormat":"bcp_test_... or bcp_live_..."}}}}