# Cobru API Documentation Complete bilingual documentation for the Cobru payment API. Locales: en, es --- # Changelog Locale: en URL: https://docs.cobru.co/en/docs/changelog 2026-04-09 [#2026-04-09] Kapso-inspired IA refresh [#kapso-inspired-ia-refresh] * Switched the shell to a darker, tighter, Kapso-like reading experience on top of Fumadocs Notebook. * Made dark mode the default and aligned light mode with the green Cobru logo. * Added `Build with AI` as a first-class platform path for coding-agent workflows. Navigation and brand refresh [#navigation-and-brand-refresh] * Replaced the old `Docs / API / Guides` tabs with a product-oriented top navbar. * Reorganized the sidebar around `Payments`, `Payouts`, `Platform`, and `Changelog`. * Increased the presence of Cobru green in active states, icons, and section accents. New hub pages [#new-hub-pages] * Added dedicated public landing pages for `Payouts`, `Platform`, and `Changelog`. * Kept Notebook Layout and Fumadocs primitives as the shell baseline. 2026-04-08 [#2026-04-08] Checkout method documentation [#checkout-method-documentation] * Rewrote Bre-B and `submitPaymentDetails` from Spotlight exports. * Added method-specific pages for PSE, Nequi, dale!, Daviplata, credit card, cash payments, and Bancolombia button. * Added `confirmDaviplataPayment` to the OpenAPI source. API reference stabilization [#api-reference-stabilization] * Fixed the production runtime issue affecting `/docs/api/reference/**`. * Added smoke coverage for API reference and critical Cobrus narrative routes. 2026-04-07 [#2026-04-07] Repo-first docs platform [#repo-first-docs-platform] * Migrated the OpenAPI contract to a repo-owned multi-file source under `openapi/src/**`. * Added governance checks for localization sync, OpenAPI validation, and critical route smoke tests. * Expanded the bilingual docs surface for payouts, services, cards, tokenization, and Celo. --- # Payouts Locale: en URL: https://docs.cobru.co/en/docs/payouts Cobru's payout surface covers transfers between Cobru users, cash withdrawal flows, bank withdrawals, and the operational visibility teams need to reconcile outbound money movement. Choose a payout flow [#choose-a-payout-flow] Recommended order [#recommended-order] 1. Review [Transfers](/en/docs/api/envios) if funds stay inside the Cobru ecosystem. 2. Use [Cash withdrawals](/en/docs/api/cash-withdrawals) for payout-to-cash operations. 3. Use [Bank withdrawals](/en/docs/api/bank-withdrawals) for bank settlement and Bre-B transfer flows. 4. Finish with [Balances](/en/docs/guides/balances) and [Movements](/en/docs/guides/movements) to harden reconciliation. Operational musts [#operational-musts] * Treat payout operations as asynchronous until your own system confirms final state. * Keep Cobru identifiers and your own reconciliation keys together from the first write. * Use webhook notifications as triggers and your own retrieval logic as the source of truth for sensitive money movement. --- # Platform Locale: en URL: https://docs.cobru.co/en/docs/platform Use the platform layer to bootstrap integrations, verify contracts, harden operational behavior, and give AI agents a trustworthy way to consume Cobru docs. Choose a platform path [#choose-a-platform-path] Platform checklist [#platform-checklist] 1. Start with [Authentication](/en/docs/authentication) to stabilize token issuance and caching. 2. Continue with [Webhooks](/en/docs/webhooks) before treating payment state as production-ready. 3. Use [Testing](/en/docs/testing) and [Production readiness](/en/docs/production-readiness) to close operational gaps. 4. Use [Build with AI](/en/docs/build-with-ai) when your team relies on coding agents or internal copilots. 5. Open the [API reference](/en/docs/api/reference) when you need exact contract detail. --- # Authentication Locale: en URL: https://docs.cobru.co/en/docs/authentication Cobru uses a layered authentication model: * `x-api-key`: your integration key * `Authorization: Bearer {access}`: a short-lived access token from `/token/refresh/` Start here [#start-here] 1. Store `x-api-key` and the `refresh` token only in backend secret storage. 2. Mint an access token from `/token/refresh/`. 3. Cache the access token centrally before making routine API calls. 4. Reuse the token until refresh is needed instead of minting on every request. Credential roles [#credential-roles] | Credential | Where to use it | Notes | | --------------- | --------------------------- | ------------------------------------------------------------------------- | | `x-api-key` | backend requests | Treat it as an integration credential and keep it out of frontend bundles | | `refresh` token | backend secret storage only | Used only to mint short-lived access tokens | | `access` token | backend requests | Cache aggressively, rotate often | Token refresh flow [#token-refresh-flow] ```bash curl -X POST https://dev.cobru.co/token/refresh/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Content-Type: application/json" \ -d '{"refresh":"'"$COBRU_REFRESH_TOKEN"'"}' ``` **Expected response** ```json { "access": "eyJ0eXAi..." } ``` The body field is `refresh`, not `refresh_token`. This discrepancy is one of the most important Cobru quirks to document internally. Required headers for API requests [#required-headers-for-api-requests] ```http x-api-key: {your_api_key} Authorization: Bearer {access} Accept: application/json Content-Type: application/json ``` Token lifetime and caching [#token-lifetime-and-caching] | Property | Recommendation | | ----------------------- | ----------------------------------------------------------- | | Observed token lifetime | about 60 minutes | | Safe cache TTL | 50 minutes | | Edge runtime caveat | in-memory caches do not persist between invocations | | Production fix | keep the token in Redis, Vercel KV, or another shared cache | Environment variables [#environment-variables] ```bash COBRU_BASE_URL=https://dev.cobru.co COBRU_API_KEY=... COBRU_REFRESH_TOKEN=... ``` Security checklist [#security-checklist] * Keep all Cobru credentials in server-side environment variables only. * Never send `x-api-key` to browsers or mobile clients. * Refresh the access token from the server, not from the frontend. * Rotate credentials when team membership changes. * Use HTTPS-only callback URLs in production. Read next [#read-next] * `/docs/getting-started` * `/docs/webhooks` * `/docs/api/authentication/refresh` --- # Build with AI Locale: en URL: https://docs.cobru.co/en/docs/build-with-ai Cobru Docs is designed to work for developers reading in the browser and for AI systems that need stable markdown and canonical URLs. What AI tools can use today [#what-ai-tools-can-use-today] Recommended workflow for coding agents [#recommended-workflow-for-coding-agents] 1. Start with `/llms.txt` to discover the smallest relevant path. 2. Pull the narrative page markdown before generating code from memory. 3. Move to `/docs/api/reference` for exact request and response shape checks. 4. Treat pages marked with verification caveats as lower-confidence sources. Truth model [#truth-model] * Public docs document only current Cobru behavior or clearly labeled legacy/menu-derived contracts. * `verified`, `legacy-doc`, and `menu-only` remain meaningful distinctions in the OpenAPI source. * Webhooks are not currently signed publicly, so agents should not model them as cryptographically trusted inputs. Best pages to pair with AI [#best-pages-to-pair-with-ai] * [Quickstart](/en/docs/getting-started) * [Authentication](/en/docs/authentication) * [Webhooks](/en/docs/webhooks) * [Production readiness](/en/docs/production-readiness) * [API Reference](/en/docs/api/reference) --- # Error Reference Locale: en URL: https://docs.cobru.co/en/docs/errors Cobru's current error model is functional but not yet ergonomic. Some validation failures show up as `403 Forbidden`, and the response shape is not consistently descriptive. Current response formats [#current-response-formats] You will most often see one of these: ```json { "error": "Error en la creacion del cobru." } ``` ```json { "payment_method_enabled": ["Not a valid string."] } ``` Error-handling strategy [#error-handling-strategy] Capture the exact HTTP status, headers, and raw response body from Cobru. Normalize Cobru's response into your own internal error type. Decide whether the error is retryable, fixable by the caller, or operational. Surface a safe customer-facing message while keeping the raw Cobru payload in logs. Known quirks [#known-quirks] | Symptom | HTTP code | Actual cause | Fix | | ------------------------------------------------------ | --------------------- | ------------------------------------- | ---------------------------------------------------------------- | | `payment_method_enabled` sent as object | `400` | Cobru expects a JSON string | `JSON.stringify()` before sending | | Missing `payer_redirect_url` or `callback` | `403` | request validation failure | send both fields on payment creation | | Credentials are present but create payment still fails | `403` | body shape may be invalid, not auth | verify `payment_method_enabled`, redirect URLs, and content type | | `refresh_token` body field fails | `400` or auth failure | wrong field name | use `refresh` | | Payment URL does not open | client bug | using `pk` path instead of `url` slug | build `{baseUrl}/{url}` | Suggested internal error categories [#suggested-internal-error-categories] | Category | Use for | | --------------------------- | -------------------------------------------------------------------- | | `configuration_error` | missing credentials, wrong environment, missing callback URL | | `request_validation_error` | malformed payloads, wrong field types, missing required fields | | `authentication_error` | invalid or expired auth material | | `provider_processing_error` | Cobru or downstream payment provider failed after request validation | | `reconciliation_error` | callback and payment status do not match your internal order state | Troubleshooting checklist [#troubleshooting-checklist] 1. Confirm you are hitting the right base URL. 2. Confirm all three credentials are present. 3. Log the exact JSON body before sending. 4. Verify `payment_method_enabled` is serialized as a string. 5. Confirm `callback` and `payer_redirect_url` are valid HTTPS URLs. 6. Keep raw responses from Cobru in logs during integration. What to log for every failed request [#what-to-log-for-every-failed-request] * internal request ID * Cobru endpoint and method * sanitized request body * HTTP status * raw Cobru response * internal error category * retry decision Retry guidance [#retry-guidance] Only retry when the failure looks transient and the operation is safe to repeat. For payment creation, prefer idempotent internal behavior even if Cobru does not yet expose a formal idempotency contract on every endpoint. Do not auto-retry malformed payloads, missing callback URLs, bad `payment_method_enabled` serialization, or wrong auth field names. These are fix-the-request failures. Desired future model [#desired-future-model] A future Cobru error model should move to `application/problem+json` with stable machine-readable error types. Until then, your integration should normalize Cobru responses into your own internal error format. --- # Quickstart Locale: en URL: https://docs.cobru.co/en/docs/getting-started Prerequisites [#prerequisites] * Cobru account with API credentials from [panel.cobru.co](https://panel.cobru.co) * Two credential values from the dashboard: `x-api-key`, `refresh_token` * Sandbox base URL: `https://dev.cobru.co` This page focuses on the shortest successful path. For the full auth model, token caching, and security guidance, continue with `/docs/authentication`. Step 1. Get an access token [#step-1-get-an-access-token] ```bash curl -X POST https://dev.cobru.co/token/refresh/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Content-Type: application/json" \ -d '{"refresh":"'"$COBRU_REFRESH_TOKEN"'"}' ``` The field is `refresh`, **not** `refresh_token`. The WooCommerce plugin documentation is wrong on this point. **Response `200`:** ```json { "access": "eyJ0eXAi..." } ``` The `access` token appears to last about 60 minutes. Cache it for at most 50 minutes. Step 2. Create a payment [#step-2-create-a-payment] ```bash curl -X POST https://dev.cobru.co/cobru/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Authorization: Bearer $COBRU_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "amount": 50000, "description": "Order #123", "expiration_days": 1, "client_assume_costs": false, "iva": 0, "payment_method_enabled": "{\"breb\":true,\"bancolombia_qr\":true,\"pse\":true}", "payer_redirect_url": "https://yourapp.com/payment-success", "callback": "https://yourapp.com/api/cobru/webhook" }' ``` `payment_method_enabled` must be a **JSON-serialized string** — run `JSON.stringify({...})` before including it in the body. Sending it as a plain object returns HTTP 400. Always include both `payer_redirect_url` and `callback`. Missing either field can return a misleading HTTP `403`, even though the root problem is request validation. **Response `201`:** ```json { "pk": 27150, "url": "3gofdf6f", "amount": "50000.00", "state": 0, "fee_amount": 2395, "currency_code": "COP", "idempotency_key": "3114242222_8de7c88b84..." } ``` Step 3. Share the payment URL [#step-3-share-the-payment-url] ```typescript // CORRECT const paymentUrl = `${COBRU_BASE_URL}/${response.url}`; // Example: https://dev.cobru.co/3gofdf6f // WRONG (WooCommerce plugin pattern — does NOT work) const paymentUrl = `${COBRU_BASE_URL}/pay/${response.pk}`; ``` From here you can: * send the link directly in email, SMS, or chat * turn it into a PNG QR using `api.qrserver.com` * use the BRE-B + QR flow documented in `/docs/guides/qr-breb` Step 4. Receive the webhook [#step-4-receive-the-webhook] ```ts export async function POST(request: Request) { const payload = await request.json(); // Persist first, process second. console.log('Cobru webhook:', payload); return new Response('ok', { status: 200 }); } ``` Cobru webhooks are not currently signed. Treat the callback as a trigger, not as a source of truth for high-risk operations. Environment variables [#environment-variables] ```bash COBRU_BASE_URL=https://dev.cobru.co # sandbox COBRU_API_KEY=your_api_key COBRU_REFRESH_TOKEN=your_refresh_token NEXT_PUBLIC_APP_URL=https://yourapp.com ``` Next steps [#next-steps] 1. Read `/docs/authentication` for token caching and security boundaries. 2. Read `/docs/webhooks` for idempotency and verification patterns. 3. Read `/docs/api/cobrus/create` for the full payment request and response contract. --- # Payments Locale: en URL: https://docs.cobru.co/en/docs Cobru is a Colombian payments platform for teams that need to launch hosted payment links, support local methods, automate collections, and operate money movement from one API. This documentation is organized for the shortest path to a safe production rollout. Every critical path is designed to work for humans reading linearly and for AI agents ingesting pages, markdown, and `llms.txt` outputs. Choose a path [#choose-a-path] What to read first [#what-to-read-first] 1. [Quickstart](/en/docs/getting-started) to create the first payment link. 2. [Authentication](/en/docs/authentication) to harden token handling. 3. [Webhooks](/en/docs/webhooks) to model async state safely. 4. [Platform](/en/docs/platform) to validate testing, troubleshooting, and AI-assisted workflows. 5. [API Reference](/en/docs/api/reference) when you need exact request and response shapes. Product surface [#product-surface] | Area | What developers use it for | | ---------------- | ----------------------------------------------------------------------------------------------------------- | | Payments | Create hosted Cobrus, calculate fees, inspect payment details, and handle local payment methods | | Payouts | Move balance, trigger cash withdrawals, bank withdrawals, and BRE-B settlement flows | | Platform | Authenticate safely, consume webhooks, test before go-live, troubleshoot incidents, and browse the contract | | Cards & Services | Operate cards, tokenization, recharges, PINs, and other surfaced product APIs | Environments [#environments] | Environment | Base URL | | ----------- | ----------------------- | | Sandbox | `https://dev.cobru.co` | | Production | `https://prod.cobru.co` | AI-first documentation model [#ai-first-documentation-model] * Every narrative page exposes a markdown copy flow. * `llms.txt` and `llms-full.txt` stay public and crawlable. * AI-specific guidance lives in [Build with AI](/en/docs/build-with-ai). * Pages with incomplete verification remain explicitly labeled instead of being normalized into false certainty. Verification and support [#verification-and-support] | Source | Role | | -------------------------- | ------------------------------------------------------------------- | | `dev.cobru.co` sandbox | Primary verification source for live behavior | | Cobru legacy API materials | Secondary source for endpoints not yet re-verified | | Cobru API menu captures | Scope source for families still pending contract extraction | | `soporte@cobru.co` | Escalation path when a contract must be confirmed before production | --- # Production Readiness Locale: en URL: https://docs.cobru.co/en/docs/production-readiness Going live with Cobru is not just a credential switch. Treat production readiness as an operational milestone with explicit checks across auth, payment creation, callbacks, observability, and support workflows. Start here [#start-here] 1. Confirm your production credentials, callback URL, and logging strategy. 2. Rehearse one payment end to end with manual reconciliation. 3. Verify support can trace a payment from your internal order ID to Cobru objects. 4. Define rollback criteria before turning on broad traffic. Go-live checklist [#go-live-checklist] Confirm production credentials are stored only in secure environment configuration and are not shared with frontend code. Switch your base URL to `https://prod.cobru.co` only after sandbox flows are consistently passing. Confirm your `callback` URL is public, HTTPS, monitored, and idempotent. Validate that your team can manually reconcile one payment from request to callback to internal order state. Make sure support can locate payments by internal order ID and Cobru `url` slug. Minimum controls before live traffic [#minimum-controls-before-live-traffic] | Area | Requirement | | ---------- | ------------------------------------------------------------------------- | | Auth | access-token caching and secure secret storage | | Payments | safe serialization of `payment_method_enabled` and reliable redirect URLs | | Webhooks | fast `200` response, persistence, deduplication, reconciliation | | Logging | request IDs, raw Cobru responses, webhook event logs | | Support | ability to trace a payment from internal order to Cobru payment object | | Monitoring | alerts on failed payment creation and failed webhook processing | Recommended launch strategy [#recommended-launch-strategy] * start with internal or low-risk traffic * keep manual reconciliation enabled during the first production days * avoid broad customer communication until you confirm callback handling is stable * document who owns incident response during launch week Known production-sensitive areas [#known-production-sensitive-areas] Some malformed payment-creation requests can still appear as `403` instead of a clean validation status. Your monitoring should preserve raw Cobru responses for diagnosis. Because Cobru callbacks are not signed today, your production system must treat them as notifications and re-check payment state before irreversible actions. Always build the hosted URL from the `url` slug returned by Cobru, not from `pk` or an older plugin pattern. Launch-day rollback criteria [#launch-day-rollback-criteria] Pause or limit live traffic if: * payment creation success drops unexpectedly * callbacks stop arriving or cannot be reconciled * you cannot match Cobru payments to internal orders reliably * support cannot diagnose failures from available logs Read next [#read-next] * `/docs/testing` * `/docs/webhooks` * `/docs/errors` * `/docs/troubleshooting` --- # Testing Locale: en URL: https://docs.cobru.co/en/docs/testing Start here [#start-here] 1. Refresh an access token in sandbox. 2. Create a real payment from your backend. 3. Open the hosted payment URL built from the returned `url` slug. 4. Confirm redirect handling and callback handling in your own system. 5. Record enough evidence to debug the run later. Sandbox environment [#sandbox-environment] | Property | Value | | --------------- | ------------------------------------------------------------------------------------------- | | Base URL | `https://dev.cobru.co` | | Purpose | development, QA, integration debugging | | Credentials | separate from production | | Fees | not representative of production economics | | Recommended use | auth validation, payment creation, hosted checkout, webhook handling, QR/BRE-B flow testing | Treat sandbox as a behavior-validation environment, not as a source of truth for production economics, settlement timing, or support procedures. Recommended test flow [#recommended-test-flow] 1. Refresh an access token. 2. Create a payment in sandbox. 3. Build the hosted payment URL from the returned `url` slug. 4. Complete the flow manually through Cobru's page. 5. Confirm your webhook receives the expected state update. Minimum integration test matrix [#minimum-integration-test-matrix] | Scenario | What to verify | | ------------------ | ------------------------------------------------------------------------------- | | Token refresh | `POST /token/refresh/` works with your credential storage and cache strategy | | Payment creation | your backend sends `payment_method_enabled` as a JSON string and gets `201` | | Hosted payment URL | your app uses `response.url`, not `response.pk`, to build the checkout URL | | Redirect handling | `payer_redirect_url` resolves correctly after payment completion | | Callback handling | your webhook endpoint persists, deduplicates, and acknowledges callbacks fast | | Payment lookup | your system can reconcile the payment after a callback or manual support action | Recommended test accounts and fixtures [#recommended-test-accounts-and-fixtures] * one low-value order for smoke tests * one order with BRE-B enabled * one order with multiple payment methods enabled * one invalid payload fixture to confirm error normalization * one webhook replay fixture for idempotency checks Local webhook testing [#local-webhook-testing] ```bash ngrok http 3000 ``` Use the generated HTTPS URL as your `callback` field in the payment creation request. What to record during every test run [#what-to-record-during-every-test-run] * request body sent to Cobru * raw Cobru response body * generated payment URL * every webhook payload * your own reconciliation result * the internal order ID or payment reference you mapped to Cobru Common sandbox pitfalls [#common-sandbox-pitfalls] Confirm you are constructing the hosted URL as `{COBRU_BASE_URL}/{url}`. Older plugin patterns using `/pay/{pk}` do not match the current behavior. Re-check body validation first. Missing `callback`, missing `payer_redirect_url`, or sending `payment_method_enabled` as an object can all surface as misleading `403` responses. That is expected. Treat callbacks as notifications and re-check payment details or internal state before releasing high-risk value. Exit criteria before production [#exit-criteria-before-production] * you can create and complete a payment end to end from your app * you can persist and deduplicate callbacks * you can manually reconcile a payment from Cobru data plus your own order state * your logs include enough information to debug a failed payment without guessing * your credentials are not hardcoded anywhere outside secure environment storage Read next [#read-next] * `/docs/production-readiness` * `/docs/webhooks` * `/docs/troubleshooting` * `/docs/errors` --- # Troubleshooting Locale: en URL: https://docs.cobru.co/en/docs/troubleshooting Use this page when the integration is failing and you need a concrete diagnosis path instead of general API guidance. Fast triage order [#fast-triage-order] 1. Confirm environment and base URL. 2. Confirm all required credentials are present. 3. Inspect the exact JSON body sent to Cobru. 4. Inspect the raw Cobru response. 5. Check whether the hosted payment URL was constructed from `url`. 6. Check whether callbacks are arriving and being deduplicated. Common failure map [#common-failure-map] | Symptom | First thing to check | | -------------------------------------- | ------------------------------------------------------ | | `403` on payment creation | request validation, not only auth | | `400` on payment creation | `payment_method_enabled` serialization | | payment page does not open | hosted URL built from `pk` instead of `url` | | callback arrives but order not updated | webhook persistence and async processing | | duplicate business actions | missing idempotency in webhook handler | | payout flow unclear | verify endpoint confidence level before implementation | Payment creation triage [#payment-creation-triage] Check `callback`, `payer_redirect_url`, content type, and the shape of `payment_method_enabled`. Cobru can surface validation failures as `403`. Send `payment_method_enabled` as a JSON string, not as a nested object. Build the payment URL as `{COBRU_BASE_URL}/{response.url}`. Do not use `/pay/{pk}`. Webhook triage [#webhook-triage] Add deduplication using `orderId`, `url`, or your own internal reference. Treat duplicate deliveries as normal until Cobru documents stronger delivery guarantees. Reconcile the payment before shipping goods or marking irreversible success. What support should always have [#what-support-should-always-have] * internal order ID * Cobru `url` slug * payment creation timestamp * raw Cobru error body when creation failed * raw webhook payload when a callback was received Escalate to Cobru when [#escalate-to-cobru-when] * sandbox and production differ in undocumented ways * a legacy-documented endpoint behaves differently from the published docs * you see sustained provider-side failures without actionable error details Related pages [#related-pages] * `/docs/testing` * `/docs/webhooks` * `/docs/errors` * `/docs/api/reference` --- # Webhooks Locale: en URL: https://docs.cobru.co/en/docs/webhooks Cobru sends a `POST` request to the `callback` URL you include when creating a payment. This is currently the main way to react to payment updates from your own backend. Start here [#start-here] 1. Treat the callback as a notification, not a source of truth. 2. Persist the raw event immediately. 3. Return HTTP `200` fast. 4. Deduplicate by Cobru identifiers or your own payment reference. 5. Reconcile before unlocking irreversible value. Current trust model [#current-trust-model] Cobru webhooks are not signed today. There is no public HMAC header or JWT verification contract. Treat the webhook as a notification, not as definitive proof. Typical payload [#typical-payload] ```json { "orderId": "123", "state": 3, "payment_method": "Bre-B", "amount": "50000.00", "url": "3gofdf6f" } ``` Payment states [#payment-states] | State | Meaning | Notes | | ----- | ----------------- | ---------------------------------------------------------------- | | `0` | Created / pending | payment object exists | | `1` | Processing | user has started or Cobru is awaiting final confirmation | | `2` | Unpaid / rejected | outcome depends on payment method | | `3` | Paid / approved | the state most teams treat as successful settlement | | `4` | Refunded | refund applied | | `5` | Expired | appears in older Cobru materials; confirm before depending on it | What a safe webhook integration must do [#what-a-safe-webhook-integration-must-do] Accept the callback, parse JSON, and persist the raw payload immediately. Return HTTP `200` quickly so Cobru does not depend on your downstream processing time. Deduplicate by `orderId`, `url`, or your own internal payment reference. Reconcile the payment before shipping goods, unlocking value, or marking irreversible business success. Recommended handler pattern [#recommended-handler-pattern] 1. Parse the payload. 2. Persist the event immediately. 3. Return HTTP `200` as fast as possible. 4. Process reconciliation and side effects asynchronously. 5. Protect downstream actions with idempotency on `orderId` or your own reference. ```ts export async function POST(request: Request) { const payload = await request.json(); await saveWebhookEvent(payload); return new Response('ok', { status: 200 }); } ``` Recommended persistence model [#recommended-persistence-model] Store at least: * raw payload * received timestamp * your internal order ID * Cobru `url` slug * Cobru `orderId` when present * processing result * replay count or deduplication marker Hardening options available today [#hardening-options-available-today] | Risk | Workaround today | | -------------------------------- | ---------------------------------------------------------------------------- | | Anyone can hit your callback URL | include your own secret in the callback query string | | Duplicate deliveries | store `orderId` and skip already-processed events | | Callback spoofing | re-check payment details with Cobru before shipping goods or unlocking value | | Operational blind spots | log every callback and expose an internal replay tool | What not to do [#what-not-to-do] * do not mark an order as permanently successful before reconciliation * do not perform heavy downstream work before returning `200` * do not trust source IP alone as your only security control * do not assume callbacks are delivered exactly once Local testing [#local-testing] ```bash ngrok http 3000 ``` Then use the public HTTPS URL as your Cobru `callback` value in sandbox. Recommended production controls [#recommended-production-controls] | Control | Why it matters | | ---------------------------------------- | ----------------------------------------------------------------- | | callback URL secret or unguessable token | reduces trivial spoofing risk | | persistent event log | lets you debug support incidents and replay failures | | idempotent processor | protects against duplicates | | reconciliation step | prevents false positives when callbacks are spoofed or incomplete | | alerting on failed processing | reduces silent payment-handling failures | Read next [#read-next] * `/docs/testing` * `/docs/production-readiness` * `/docs/troubleshooting` * `/docs/api/cobrus/create` --- # Balances Locale: en URL: https://docs.cobru.co/en/docs/guides/balances The balance endpoint is documented in legacy Cobru materials. The route is useful, but the full contract still needs a fresh sandbox verification pass. Endpoint [#endpoint] `GET /balance/` Typical use cases [#typical-use-cases] * pre-flight checks before transfers or withdrawals * dashboard balance synchronization * reconciliation and treasury views Response shape seen in legacy docs [#response-shape-seen-in-legacy-docs] ```json { "balance": "14179.25", "balance_cop": "14179.25", "balance_usd": "9995.00", "balance_ars": "10000.00", "balance_mxn": "96536.31", "balance_brl": "89772737.20" } ``` Example request [#example-request] ```bash curl -X GET https://dev.cobru.co/balance/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Authorization: Bearer $COBRU_ACCESS_TOKEN" ``` ```ts const response = await fetch('https://dev.cobru.co/balance/', { method: 'GET', headers: { 'x-api-key': process.env.COBRU_API_KEY!, Authorization: `Bearer ${accessToken}`, }, }); const balance = await response.json(); console.log(balance.balance_cop); ``` ```python import requests response = requests.get( "https://dev.cobru.co/balance/", headers={ "x-api-key": COBRU_API_KEY, "Authorization": f"Bearer {access_token}", }, ) print(response.json()) ``` ```php request('GET', 'https://dev.cobru.co/balance/', [ 'headers' => [ 'x-api-key' => getenv('COBRU_API_KEY'), 'Authorization' => 'Bearer ' . $accessToken, ], ]); $balance = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR); var_dump($balance); ``` Integration guidance [#integration-guidance] Use balance reads as an operational snapshot, not as the only source of truth for settlement. Pair them with movements and payment status when building reconciliation. For dashboards, short-lived caching is reasonable. For payouts or withdrawals, re-read the balance immediately before executing the operation. The legacy response includes COP, USD, ARS, MXN, and BRL balances. Confirm which balances are actually meaningful for your account type before showing them in production UI. --- # Movements Locale: en URL: https://docs.cobru.co/en/docs/guides/movements Cobru's movements contract still comes from legacy materials. The route shape is promising, but the parameters and response need a fresh verification pass before you depend on them for automated accounting. Why this page matters [#why-this-page-matters] Movement history is a recurring operational requirement across payments, transfers, withdrawals, and cards. Endpoint pattern [#endpoint-pattern] `GET /movements/movements_by_types/?{type_req}=true&per_page={number}&page_num={number}` Supported `type_req` values from Spotlight: * `by_cobrus` * `by_withdraws` * `by_sends` * `by_other_payments` Send only one type filter at a time. Example request [#example-request] ```bash curl -G https://dev.cobru.co/movements/movements_by_types/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Authorization: Bearer $COBRU_ACCESS_TOKEN" \ --data-urlencode "by_cobrus=true" \ --data-urlencode "per_page=10" \ --data-urlencode "page_num=1" ``` ```ts const url = new URL('https://dev.cobru.co/movements/movements_by_types/'); url.searchParams.set('by_cobrus', 'true'); url.searchParams.set('per_page', '10'); url.searchParams.set('page_num', '1'); const response = await fetch(url, { headers: { 'x-api-key': process.env.COBRU_API_KEY!, Authorization: `Bearer ${accessToken}`, }, }); const movements = await response.json(); console.log(movements); ``` ```python import requests response = requests.get( "https://dev.cobru.co/movements/movements_by_types/", headers={ "x-api-key": COBRU_API_KEY, "Authorization": f"Bearer {access_token}", }, params={ "by_cobrus": "true", "per_page": 10, "page_num": 1, }, ) print(response.json()) ``` ```php request('GET', 'https://dev.cobru.co/movements/movements_by_types/', [ 'headers' => [ 'x-api-key' => getenv('COBRU_API_KEY'), 'Authorization' => 'Bearer ' . $accessToken, ], 'query' => [ 'by_cobrus' => 'true', 'per_page' => 10, 'page_num' => 1, ], ]); $movements = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR); var_dump($movements); ``` Reconciliation checklist [#reconciliation-checklist] Persist Cobru webhook payloads first, then process them asynchronously. Reconcile a movement row with payment or withdrawal identifiers, not only by amount. Re-run a historical pull when a webhook fails, arrives late, or produces ambiguous state. Integration warnings [#integration-warnings] Spotlight explicitly says not to send all type flags at the same time. Build your sync jobs to query one movement family per request. The sample response includes presentational fields such as `img` plus payer and tax fields. Treat those as informational until the current contract is revalidated. Prefer `pk`, `reference_cobru`, `url`, and operation-specific IDs over derived display fields when joining movement rows to internal records. --- # Bre-B payment flow Locale: en URL: https://docs.cobru.co/en/docs/guides/qr-breb What this guide covers [#what-this-guide-covers] This guide replaces the previous QR-only narrative and documents the Bre-B flow as it appears in Cobru's original Spotlight materials. The flow has two parts: 1. Create a cobru with Bre-B enabled in `payment_method_enabled` 2. Submit payment details to `POST /{url}` with `payment: "breb"` Public copy uses Bre-B, but request payloads keep the backend literal exactly as shown in the request contract: `payment: "breb"` and `"breb": true` inside `payment_method_enabled`. Bre-B output modes [#bre-b-output-modes] There are two very different ways to ship a Bre-B experience with Cobru: | Mode | What you generate | Requires hosted Cobru page | What the payer scans | | --------------- | ----------------------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------- | | Hosted link QR | a QR that points to `https://dev.cobru.co/{slug}` or `https://prod.cobru.co/{slug}` | yes | a URL that opens the Cobru page | | Native Bre-B QR | a QR generated from Cobru's Bre-B payload string | no | an EMV/Bre-B payload string processed by banking apps | If your goal is specifically to generate a **Bre-B QR without the payment link**, you need the second path: obtain the Bre-B payload string from Cobru and render the QR yourself. Step 1 — Create the cobru [#step-1--create-the-cobru] ```json { "amount": 20000, "description": "Cobro Bre-B", "expiration_days": 1, "client_assume_costs": false, "iva": 0, "payment_method_enabled": "{\"breb\":true}", "payer_redirect_url": "https://yourapp.com/payment/success", "callback": "https://yourapp.com/api/cobru/webhook" } ``` Spotlight and later integration learnings agree on one critical quirk: `payment_method_enabled` must be a JSON string, not a nested object. Step 1.5 — Enable the right Bre-B capability [#step-15--enable-the-right-bre-b-capability] The create step must enable Bre-B with `"breb": true` inside `payment_method_enabled`. Later deep research also found a second checkout literal, `breb_qr`, used by Cobru's hosted checkout internals. For documentation purposes, treat them like this: | Capability | Where it comes from | What it means | | ------------------------------------------ | ------------------- | -------------------------------------------------------- | | `"breb": true` in `payment_method_enabled` | request payload | Bre-B should be offered on the cobru | | `payment: "breb"` | Spotlight | direct Bre-B payment-details request | | `payment: "breb_qr"` | deep research | QR-focused Bre-B variant seen in later checkout analysis | Cobru's later sandbox research observed direct `payment: "breb"` as commercially gated or disabled in some environments. Keep both variants in mind when implementing a native Bre-B QR flow. Step 2 — Submit Bre-B payment details [#step-2--submit-bre-b-payment-details] Call the cobru slug returned by `POST /cobru/`: `POST /{url}` ```json { "payment": "breb" } ``` The original Spotlight materials describe Bre-B as a fast bank-transfer method tied to the user's Bre-B app or key (`llaves`). Generate a native Bre-B QR without the payment link [#generate-a-native-bre-b-qr-without-the-payment-link] This is the section most teams are actually looking for. If you do **not** want to send the payer to the hosted Cobru page, your flow is: 1. create the cobru with Bre-B enabled 2. call `POST /{url}` for the Bre-B checkout variant 3. extract the Bre-B payload string returned by Cobru 4. generate the QR image inside your own frontend or backend 5. show the QR plus the Bre-B key to the payer Which field should you use for the QR? [#which-field-should-you-use-for-the-qr] The source materials are inconsistent, so your implementation should normalize all known field names: | Source | Field name | Meaning | | ---------------------------- | ---------------------------- | ------------------------------------------------------------- | | Spotlight | `check_qr` | string used to build the QR | | Spotlight response example | `qr_value` | QR payload shown inside `api.paymentorder` | | later deep research | `payment_details.qr_bitcoin` | EMV payload string found in Cobru's hosted checkout internals | | Spotlight and later research | `key_value` | Bre-B key shown to the user | Practical rule: * first look for `check_qr` * then fall back to `qr_value` * if you are integrating against the later hosted-checkout path, also check `payment_details.qr_bitcoin` Example normalization logic [#example-normalization-logic] ```ts const qrPayload = response?.check_qr ?? response?.qr_value ?? response?.payment_details?.qr_bitcoin ?? response?.fields?.check_qr ?? response?.fields?.qr_value; const keyValue = response?.key_value ?? response?.payment_details?.key_value ?? response?.fields?.key_value; if (!qrPayload) { throw new Error('Cobru did not return a Bre-B QR payload'); } ``` Example QR generation [#example-qr-generation] ```ts import QRCode from 'qrcode'; const qrDataUrl = await QRCode.toDataURL(qrPayload, { errorCorrectionLevel: 'M', margin: 1, width: 320, }); ``` Use the generated image in your own checkout UI. Do **not** encode the hosted Cobru URL if your goal is a native Bre-B QR. Response fields to show in your UI [#response-fields-to-show-in-your-ui] | Field | Show it to the payer? | Why | | -------------------------------------- | --------------------- | ------------------------------------------------------------- | | `qr_value` / `check_qr` / `qr_bitcoin` | yes | this is the payload you turn into the QR | | `key_value` | yes | fallback Bre-B key when the payer wants to type or copy a key | | `amount` | yes | helps the payer confirm the charge | | `state` | internal and UI | the transaction starts as pending | | `GOrdenId` | internal | useful for correlation and later status checks | Time-to-live [#time-to-live] Spotlight says `qr_value` and `key_value` live for **5 minutes**. Later reverse engineering also observed `time_to_complete: 520` seconds in Cobru's page logic, which is roughly **8.6 minutes**. Treat the operational rule as: * your UX should assume a **very short-lived** Bre-B instruction * refresh or regenerate the QR when the payment window expires * never reuse an old Bre-B payload for a new transaction Current limitation [#current-limitation] Later deep research found that Cobru does **not** expose a simple static Bre-B QR that any payer can scan forever. The native Bre-B QR is transaction-scoped and, in later sandbox testing, may require real payer identification data or commercial enablement. That means: * you can generate a Bre-B QR without using the hosted payment link * but you still depend on Cobru returning a transaction-specific Bre-B payload first * this is not the same thing as having a reusable static merchant QR Alternative native QR path seen in later research [#alternative-native-qr-path-seen-in-later-research] Later checkout research also found a QR-focused variant: ```json { "payment": "breb_qr" } ``` Important caveats from that research: * it was observed in a later Cobru checkout implementation, not in the original Spotlight contract * sandbox testing suggested the payer's document data may be required * the response path looked closer to `payment_details.qr_bitcoin` than the Spotlight `check_qr` wording Use it only if: * direct `breb` is not available in your environment * Cobru support confirms `breb_qr` for your account * you are prepared to test it with real sandbox-compatible payer data Expected response shape [#expected-response-shape] Spotlight shows a response that contains both an `api.paymentorder` object and an `api.cobru` object. The most important Bre-B fields are: | Field | Meaning | | ----------- | ----------------------------------------- | | `method` | `breb` | | `franchise` | `breb` | | `qr_value` | QR payload shown by Cobru in the response | | `key_value` | Bre-B key shown to the user | | `GOrdenId` | gateway-side order identifier | Example excerpt from the original materials: ```json [ { "model": "api.paymentorder", "fields": { "method": "breb", "franchise": "breb", "state": "PENDIENTE", "amount": "20000.00", "qr_value": "9893839849384938434.COM.CRB.LLA04...", "key_value": "@llave0343" } }, { "model": "api.cobru", "fields": { "url": "urmndopt" } } ] ``` Expiration window [#expiration-window] The Spotlight materials explicitly state that both `qr_value` and `key_value` are valid for **5 minutes**. Treat them as short-lived payment instructions, not reusable identifiers. How this differs from the QR addendum [#how-this-differs-from-the-qr-addendum] The Spotlight contract above is the source of truth for the Bre-B payment flow. A later verified integration pattern also exists: * create a cobru with Bre-B enabled * build the hosted Cobru URL from the returned slug * render an external QR PNG that points to the hosted payment page * send it through channels such as WhatsApp That QR pattern is useful when your product needs to distribute a scannable payment link, but it is an addendum on top of the original Bre-B flow, not the base contract. Verified addendum: Cobru does not expose a PNG QR endpoint. If your UX needs a shareable QR image, generate it yourself from the hosted Cobru URL. Recommended decision tree [#recommended-decision-tree] | If you need... | Recommended path | | -------------------------------- | --------------------------------------------------------------------------------- | | the simplest MVP | use the hosted Cobru link and generate a QR that points to the payment page | | a native Bre-B QR in your own UI | call the Bre-B payment-details flow and render the returned payload yourself | | a reusable static bank-app QR | do not assume Cobru provides this today; ask Cobru or use an alternative provider | When to use Bre-B [#when-to-use-bre-b] Use Bre-B when: * the payer can complete an interoperable bank transfer * your checkout should show Bre-B as a first-class option * you can tolerate short-lived payment instructions and webhook-driven confirmation If you need a hosted redirect flow with explicit bank selection, PSE is the better fit. Related pages [#related-pages] * [Create a cobru](/en/docs/api/cobrus/create) * [Submit payment details](/en/docs/api/cobrus/payment-details) * [PSE bank codes](/en/docs/api/cobrus/pse-banks) * [PSE payments](/en/docs/api/cobrus/pse) --- # White-label Locale: en URL: https://docs.cobru.co/en/docs/guides/whitelabel Cobru's hosted payment flows can still feel integrated into your own product if you design the handoff carefully. The original Spotlight material also documents a white-label user registration surface that is important for embedded financial products. White-label onboarding and brand-prefixed usernames come from legacy Cobru documentation. Publish or ship only after confirming the current contract with your Cobru team. What this capability covers [#what-this-capability-covers] * registering users under a partner or brand namespace * collecting categories and subcategories before registration * confirming email and phone * embedding Cobru-owned flows inside your product experience Registration workflow [#registration-workflow] Fetch categories from `GET /category/` and the matching subcategories from `GET /subcategory?category_id=...`. Collect the registration payload, including `brand`, `username`, `documents`, and legal identity fields. Create the user with `POST /user/`. Complete post-registration verification flows such as email and phone confirmation. Example registration payload [#example-registration-payload] ```json { "username": "09906786442", "first_name": "Test", "last_name": "User", "email": "test@example.com", "password": "12345678", "phone": "09906786442", "document_type": "0", "document_number": "11111122223", "country_code": "+57", "gender": 2, "date_birth": "2001-08-08", "type_person": 1, "date_expiration": "2019-08-08", "subcategory": 745, "category": 99, "platform": "ios", "brand": "MY_BRAND" } ``` ```ts const response = await fetch('https://dev.cobru.co/user/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': process.env.COBRU_API_KEY!, }, body: JSON.stringify(userPayload), }); const createdUser = await response.json(); console.log(createdUser.username); ``` ```python import requests response = requests.post( "https://dev.cobru.co/user/", headers={ "x-api-key": COBRU_API_KEY, "Content-Type": "application/json", }, json=user_payload, ) print(response.json()) ``` ```php request('POST', 'https://dev.cobru.co/user/', [ 'headers' => [ 'x-api-key' => getenv('COBRU_API_KEY'), 'Content-Type' => 'application/json', ], 'json' => $userPayload, ]); $createdUser = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR); var_dump($createdUser); ``` Integration rules [#integration-rules] The legacy docs state that the request sends a plain `username`, while Cobru may return a stored username with the `brand` prefix applied. Do not assume the input and persisted values are identical. Category and subcategory should be treated as a server-driven taxonomy. Always fetch them before registration rather than hard-coding IDs in the client. The onboarding payload references a `documents` array with document IDs and URLs. Design a controlled upload flow and do not assume Cobru stores arbitrary external URLs forever. UX recommendations [#ux-recommendations] * always describe the next step before redirecting the user * use your own reference ID in the `callback` URL * store Cobru's `pk`, `url`, and `idempotency_key` * design a return URL that confirms status and next actions * document payment-method-specific UX, especially for BRE-B and QR --- # Available banks Locale: en URL: https://docs.cobru.co/en/docs/api/bank-withdrawals/banks-list The third-party withdrawal bank list is documented in legacy Cobru materials, while a newer country-based variant appears in additional exports. Confirm which one is current for your integration. Best-known endpoint [#best-known-endpoint] `GET /bank_list_third_party_withdraw/` Response fields seen in older docs [#response-fields-seen-in-older-docs] | Field | Type | Notes | | ------ | -------- | ------------------------- | | `id` | `number` | Internal bank identifier. | | `name` | `string` | Human-readable bank name. | Newer variant mentioned in additional materials [#newer-variant-mentioned-in-additional-materials] Some newer withdrawal exports also reference: `GET /bank_list/?country={country_code}` Treat that country-parameterized variant as a candidate newer contract until Cobru confirms it. --- # BRE-B transfer Locale: en URL: https://docs.cobru.co/en/docs/api/bank-withdrawals/bre-b BRE-B appears in Cobru's product surface in two different ways: 1. as a payment method inside `POST /cobru/` 2. as a bank-transfer or withdrawal capability in the bank-withdrawals family The QR payment flow is much better understood than the withdrawal contract. Verify the exact bank-withdrawal BRE-B endpoint with Cobru before implementing it. Best-known endpoint candidate [#best-known-endpoint-candidate] `POST /withdraw/co/` What this page is for [#what-this-page-is-for] Use this page when your product requires moving funds to a Colombian bank destination using a BRE-B-linked withdrawal or transfer capability rather than collecting payment through a Cobru checkout flow. What still needs confirmation [#what-still-needs-confirmation] * final endpoint path and request shape * supported destination identifiers for the beneficiary * whether BRE-B withdrawals share the same state model as other bank withdrawals * whether callbacks or webhooks deliver final settlement events --- # Withdraw to Argentina Locale: en URL: https://docs.cobru.co/en/docs/api/bank-withdrawals/create-argentina This cross-border flow is documented from legacy Cobru exports. Re-verify it with Cobru before shipping an Argentina payout experience. Endpoint [#endpoint] `POST /withdraw/ar/` Request fields seen in legacy documentation [#request-fields-seen-in-legacy-documentation] | Field | Type | Required | Notes | | ----------------- | -------- | ----------- | ---------------------------------------------- | | `amount` | `number` | yes | Withdrawal amount. | | `currency_code` | `string` | yes | Legacy materials document `ARS`. | | `bank_name` | `string` | yes | Destination bank name. | | `cbu` | `string` | conditional | Traditional Argentine bank account identifier. | | `cvu` | `string` | conditional | Virtual account identifier when supported. | | `account_phone` | `string` | yes | Beneficiary phone number. | | `account_email` | `string` | yes | Beneficiary email. | | `callback` | `string` | no | Optional callback URL. | | `idempotency_key` | `string` | no | Optional idempotency key. | | `description` | `string` | no | Optional payout note. | | `platform` | `string` | no | Optional source or platform value. | Production notes [#production-notes] * Confirm whether Cobru expects `cbu`, `cvu`, or both depending on the beneficiary rail. * Validate FX assumptions and payout timing before exposing this flow to customers. --- # Withdraw to Brazil Locale: en URL: https://docs.cobru.co/en/docs/api/bank-withdrawals/create-brazil This cross-border flow is documented from legacy Cobru exports. Re-verify it in sandbox before using it for production payouts. Endpoint [#endpoint] `POST /withdraw/br/` Request fields seen in legacy documentation [#request-fields-seen-in-legacy-documentation] | Field | Type | Required | Notes | | ----------------- | -------- | ----------- | ---------------------------------------------------------------- | | `amount` | `number` | yes | Withdrawal amount. | | `currency_code` | `string` | yes | Legacy materials document `BRL`. | | `pix_key` | `string` | yes | PIX key value. | | `pix_key_type` | `string` | yes | PIX key type. | | `cpf` | `string` | conditional | Individual taxpayer identifier when the beneficiary is a person. | | `cnpj` | `string` | conditional | Company taxpayer identifier when the beneficiary is a business. | | `account_phone` | `string` | yes | Beneficiary phone number. | | `account_email` | `string` | yes | Beneficiary email. | | `callback` | `string` | no | Optional callback URL. | | `idempotency_key` | `string` | no | Optional idempotency key. | | `description` | `string` | no | Optional payout note. | | `platform` | `string` | no | Optional platform or source identifier. | | `longitude` | `number` | no | Optional geolocation field in older exports. | | `latitude` | `number` | no | Optional geolocation field in older exports. | Production notes [#production-notes] * Confirm currency, beneficiary schema, FX model, fee schedule, and settlement times with Cobru. * Validate PIX key type and CPF/CNPJ requirements before sending the request. --- # Withdraw to Mexico Locale: en URL: https://docs.cobru.co/en/docs/api/bank-withdrawals/create-mexico This cross-border flow is documented from legacy Cobru exports. Re-verify it with Cobru before using it in production. Endpoint [#endpoint] `POST /withdraw/mx/` Request fields seen in legacy documentation [#request-fields-seen-in-legacy-documentation] | Field | Type | Required | Notes | | ----------------- | -------- | -------- | ------------------------------------------ | | `amount` | `number` | yes | Withdrawal amount. | | `currency_code` | `string` | yes | Legacy materials document `MXN`. | | `clabe` | `string` | yes | Standard Mexican CLABE account identifier. | | `beneficiary` | `string` | yes | Beneficiary name. | | `account_phone` | `string` | yes | Beneficiary phone number. | | `account_email` | `string` | yes | Beneficiary email. | | `callback` | `string` | no | Optional callback URL. | | `idempotency_key` | `string` | no | Optional idempotency key. | | `description` | `string` | no | Optional payout note. | | `platform` | `string` | no | Optional source or platform value. | Production notes [#production-notes] * Confirm CLABE validation requirements, settlement currency, and failure modes with Cobru. * Make beneficiary validation explicit in your own UI before submitting the payout. --- # Create withdrawal Locale: en URL: https://docs.cobru.co/en/docs/api/bank-withdrawals/create This page documents the best-known Colombian third-party withdrawal contract from legacy Cobru exports. Re-verify the exact behavior in sandbox before making it a production dependency. Endpoint [#endpoint] `POST /thirdpartywithdraw/` Request fields seen in legacy documentation [#request-fields-seen-in-legacy-documentation] | Field | Type | Required | Notes | | ------------------------------ | -------- | -------- | --------------------------------------------------- | | `amount` | `number` | yes | Withdrawal amount. | | `account_holder_name` | `string` | yes | Beneficiary full name. | | `account_type` | `string` | yes | Account type accepted by the destination bank. | | `account_holder_document` | `string` | yes | Beneficiary document number. | | `account_holder_document_type` | `string` | yes | Document type code expected by Cobru. | | `account_number` | `string` | yes | Destination account number. | | `account_phone` | `string` | yes | Beneficiary phone number. | | `account_email` | `string` | yes | Beneficiary email. | | `bank_name` | `string` | no | Bank name or bank descriptor when required. | | `description` | `string` | no | Optional payout note or internal description. | | `callback` | `string` | no | Optional callback URL for status updates. | | `idempotency_key` | `string` | no | Best-known field for deduplicating payout attempts. | What to confirm with Cobru before go-live [#what-to-confirm-with-cobru-before-go-live] * whether `bank_name` should now be replaced by a bank code or bank ID * the accepted values for `account_type` and `account_holder_document_type` * whether callbacks are still supported or if webhooks replaced them * payout settlement timeline and terminal states Error signals seen in older materials [#error-signals-seen-in-older-materials] | Signal | Meaning | | ------ | --------------------------------------------------------------- | | `R010` | Invalid account data or payout rejection by banking validation. | | `P002` | Processing or provider-side failure. | | `E001` | Generic validation or downstream provider error. | Production notes [#production-notes] * Always send an idempotency key if Cobru confirms it remains supported. * Keep the withdrawal identifier returned by Cobru to reconcile async state changes. * Treat bank withdrawals as asynchronous even when the initial response is successful. --- # Withdrawal details Locale: en URL: https://docs.cobru.co/en/docs/api/bank-withdrawals/details This detail view is documented from legacy Cobru payout materials and still needs fresh verification from a live environment. Endpoint [#endpoint] `GET /thirdpartywithdraw/{id}` Path parameter [#path-parameter] | Field | Type | Description | | ----- | -------- | --------------------------------- | | `id` | `number` | Cobru bank-withdrawal identifier. | What to expect [#what-to-expect] Use this endpoint to retrieve the latest payout state and the final bank-settlement record for one withdrawal. Older materials suggest the response mirrors most fields seen in the listing endpoint, but scoped to a single payout. --- # Bank withdrawals Locale: en URL: https://docs.cobru.co/en/docs/api/bank-withdrawals This family mixes multiple evidence levels: older Colombian third-party withdrawal contracts, newer country-specific exports, and product-menu visibility. Treat each endpoint page as a separate confidence level and verify the exact flow you plan to ship. Cobru's API menu exposes a broad bank-withdrawal surface across Colombia and other countries. It is the main family to use when funds must leave Cobru and settle into a beneficiary bank account instead of another Cobru user wallet. When to use bank withdrawals [#when-to-use-bank-withdrawals] * disburse funds to beneficiary bank accounts * build operational payout flows for vendors, customers, or internal treasury * support country-specific withdrawal rails such as Colombia, Brazil, Argentina, Mexico, or BRE-B-linked bank movement Coverage visible today [#coverage-visible-today] | Operation | Method | Path | Confidence | | ------------------------------ | ------ | ---------------------------------- | ------------------ | | Available banks list | `GET` | `/bank_list_third_party_withdraw/` | legacy-doc | | Your withdrawals | `GET` | `/thirdpartywithdraw/` | legacy-doc | | Create withdrawal to Colombia | `POST` | `/thirdpartywithdraw/` | legacy-doc | | Withdrawal details | `GET` | `/thirdpartywithdraw/{id}` | legacy-doc | | Cancel withdrawal | `POST` | `/cancelthirdpartywithdraw/` | legacy-doc | | BRE-B transfer | `POST` | `/withdraw/co/` | menu plus research | | Create withdrawal to Brazil | `POST` | `/withdraw/br/` | legacy-doc | | Create withdrawal to Mexico | `POST` | `/withdraw/mx/` | legacy-doc | | Create withdrawal to Argentina | `POST` | `/withdraw/ar/` | legacy-doc | Withdrawal workflow [#withdrawal-workflow] Resolve beneficiary rails first, usually by fetching supported banks or by validating the country-specific account identifier such as PIX, CBU/CVU, or CLABE. Create the withdrawal with beneficiary identity, banking data, amount, and optional idempotency or callback fields when documented. Reconcile the payout asynchronously from list and detail endpoints. Do not assume bank withdrawals settle instantly. Common concerns to solve early [#common-concerns-to-solve-early] * beneficiary KYC and document-type mapping * idempotency for payout retries * callback or webhook delivery guarantees * fees, FX, and final settled amount * payout rejection handling by country and bank rail --- # Your withdrawals Locale: en URL: https://docs.cobru.co/en/docs/api/bank-withdrawals/list This listing comes from legacy Cobru payout materials. Filters, pagination, and country segmentation still need live verification. Endpoint [#endpoint] `GET /thirdpartywithdraw/` Fields seen in legacy responses [#fields-seen-in-legacy-responses] | Field | Type | Notes | | ---------------- | -------- | ---------------------------------------------------- | | `type` | `string` | Withdrawal type or rail identifier. | | `pk` | `number` | Cobru payout identifier. | | `state` | `string` | Payout state. | | `amount` | `number` | Requested amount. | | `payed_amount` | `number` | Net paid amount after fees and adjustments. | | `fee` | `number` | Cobru fee. | | `fee_iva` | `number` | IVA applied to fees. | | `gmf` | `number` | Colombian financial transaction tax when applicable. | | `account_number` | `string` | Destination account number. | | `description` | `string` | Optional payout description. | | `date_created` | `string` | Withdrawal creation timestamp. | | `date_consigned` | `string` | Consignment timestamp when available. | | `date_deposited` | `string` | Deposit completion timestamp when available. | | `date_rejected` | `string` | Rejection timestamp when available. | Additional query behavior seen in older docs [#additional-query-behavior-seen-in-older-docs] Legacy materials also mention querying the list by `idempotency_key` to find a previously submitted payout attempt. --- # Authentication API Locale: en URL: https://docs.cobru.co/en/docs/api/authentication The Cobru API currently uses a layered model: * `x-api-key` * `Authorization: Bearer {access}` Available endpoint [#available-endpoint] | Endpoint | Method | Status | | ----------------- | ------ | -------------------------------------- | | `/token/refresh/` | `POST` | verified against live sandbox behavior | Notes for implementers [#notes-for-implementers] * The body field is `refresh`, not `refresh_token`. * Keep the API key, refresh token, and access token server-side. * Cache the access token for no more than 50 minutes. Continue with the `Refresh token` page for request and response details. --- # Refresh token Locale: en URL: https://docs.cobru.co/en/docs/api/authentication/refresh Endpoint [#endpoint] `POST /token/refresh/` Verified against Cobru sandbox behavior and internal integration learnings. Headers [#headers] ```http x-api-key: {your_api_key} Content-Type: application/json ``` Body [#body] ```json { "refresh": "your_refresh_token" } ``` Response [#response] ```json { "access": "eyJ0eXAi..." } ``` curl [#curl] ```bash curl -X POST https://dev.cobru.co/token/refresh/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Content-Type: application/json" \ -d '{"refresh":"'"$COBRU_REFRESH_TOKEN"'"}' ``` Node.js [#nodejs] ```ts const response = await fetch('https://dev.cobru.co/token/refresh/', { method: 'POST', headers: { 'x-api-key': process.env.COBRU_API_KEY!, 'Content-Type': 'application/json', }, body: JSON.stringify({ refresh: process.env.COBRU_REFRESH_TOKEN, }), }); const data = await response.json(); ``` Python [#python] ```python import os import requests response = requests.post( "https://dev.cobru.co/token/refresh/", headers={ "x-api-key": os.environ["COBRU_API_KEY"], "Content-Type": "application/json", }, json={"refresh": os.environ["COBRU_REFRESH_TOKEN"]}, ) data = response.json() ``` --- # Create card Locale: en URL: https://docs.cobru.co/en/docs/api/cards/create Card issuance is documented from legacy Cobru exports. Re-verify issuer behavior and PCI handling before shipping a live card program. Endpoint [#endpoint] `POST /cobru/debit/create_and_reload_card/` Best-known request body [#best-known-request-body] Card creation is documented as a call to the shared create-and-reload endpoint with an amount of `0`. ```json { "amount": 0 } ``` Response fields seen in legacy documentation [#response-fields-seen-in-legacy-documentation] | Field | Type | Notes | | -------------------- | -------- | ------------------------------------ | | `balance` | `number` | Current card balance. | | `cvv` | `string` | Card security code. | | `display_expiration` | `string` | Human-readable expiration value. | | `id` | `number` | Card identifier. | | `masked_pan` | `string` | Masked card number. | | `max_balance` | `number` | Maximum allowed card balance. | | `state` | `string` | Card state. | | `support_token` | `string` | Provider or support reference token. | Questions to settle before full rollout [#questions-to-settle-before-full-rollout] * issuance type: single-use or reusable * funding source * cardholder identity requirements * PCI scope and who hosts PAN display * expiration and freeze behavior --- # Card details and list Locale: en URL: https://docs.cobru.co/en/docs/api/cards/details Card retrieval is documented from legacy Cobru exports. Confirm whether detail and list are still variants of the same endpoint in the current product. Best-known endpoint [#best-known-endpoint] `GET /cobru/debit/get_card/` Query behavior seen in older docs [#query-behavior-seen-in-older-docs] * call the endpoint without `card_id` to list cards * pass `?card_id={card_id}` to retrieve one card Fields seen in legacy responses [#fields-seen-in-legacy-responses] | Field | Type | Notes | | -------------------- | -------- | -------------------------- | | `id` | `number` | Card identifier. | | `masked_pan` | `string` | Masked card number. | | `display_expiration` | `string` | Human-readable expiration. | | `balance` | `number` | Current card balance. | | `state` | `string` | Card state. | --- # Freeze card Locale: en URL: https://docs.cobru.co/en/docs/api/cards/freeze Freeze and unfreeze are documented from legacy Cobru exports. Confirm reversibility and pending-authorization behavior before exposing this feature to end users. Endpoint [#endpoint] `POST /cobru/debit/freeze_card/` Request fields seen in legacy documentation [#request-fields-seen-in-legacy-documentation] | Field | Type | Required | Notes | | --------- | --------- | -------- | -------------------------------------- | | `card_id` | `number` | yes | Card identifier. | | `freeze` | `boolean` | yes | `true` to freeze, `false` to unfreeze. | --- # Virtual cards Locale: en URL: https://docs.cobru.co/en/docs/api/cards The cards family is backed by legacy Cobru exports rather than a freshly verified public contract. The endpoint surface is meaningful, but you should still validate issuer behavior, PCI scope, and operational states before launch. Cobru's API menu includes a `Tarjetas` section, indicating a broader programmable cards capability layered on top of the wallet and balance infrastructure. Choose a card workflow [#choose-a-card-workflow] Visible operations [#visible-operations] | Operation | Method | Path | Confidence | | --------------------- | ------ | -------------------------------------- | ---------- | | Create card | `POST` | `/cobru/debit/create_and_reload_card/` | legacy-doc | | Top up card | `POST` | `/cobru/debit/create_and_reload_card/` | legacy-doc | | Card details and list | `GET` | `/cobru/debit/get_card/` | legacy-doc | | Movements | `GET` | `/cobru/debit/get_transactions/` | legacy-doc | | Freeze card | `POST` | `/cobru/debit/freeze_card/` | legacy-doc | Launch constraints [#launch-constraints] * confirm issuer SLA and operational ownership before enabling cards for customers * map PCI, PII, and support access rules before exposing card data in internal tooling * treat freeze and unfreeze as high-sensitivity actions with audit logs --- # Card movements Locale: en URL: https://docs.cobru.co/en/docs/api/cards/movements Card movement history is documented from legacy Cobru exports. Confirm pagination and posted vs pending semantics with Cobru before building reconciliation logic on top of it. Best-known endpoint [#best-known-endpoint] `GET /cobru/debit/get_transactions/?card_id={card_id}` Query parameters seen in legacy docs [#query-parameters-seen-in-legacy-docs] | Field | Type | Required | Notes | | ---------- | -------- | -------- | --------------------- | | `card_id` | `number` | yes | Card identifier. | | `per_page` | `number` | no | Optional page size. | | `page_num` | `number` | no | Optional page number. | --- # Top up card Locale: en URL: https://docs.cobru.co/en/docs/api/cards/topup Card reload is documented from legacy Cobru exports. Re-verify settlement timing and shared endpoint behavior before production use. Endpoint [#endpoint] `POST /cobru/debit/create_and_reload_card/` Request fields seen in legacy documentation [#request-fields-seen-in-legacy-documentation] | Field | Type | Required | Notes | | --------- | -------- | -------- | ------------------------------- | | `amount` | `number` | yes | Balance to add to the card. | | `card_id` | `number` | yes | Existing Cobru card identifier. | Important implementation note [#important-implementation-note] Older Cobru materials describe creation and reload as two modes of the same endpoint. Treat that shared-endpoint behavior as real until Cobru confirms a newer split contract. --- # Cancel withdrawal Locale: en URL: https://docs.cobru.co/en/docs/api/cash-withdrawals/cancel Cancellation is documented in legacy Cobru materials, but you should verify the allowed cancellation window and provider side effects live before exposing it to customers. Endpoint [#endpoint] `POST /cancelcashwithdraw/` Request fields [#request-fields] | Field | Type | Required | Notes | | ----- | -------- | -------- | ------------------------------------- | | `id` | `number` | yes | Cash-withdrawal identifier to cancel. | Example body [#example-body] ```json { "id": 123456 } ``` Operational notes [#operational-notes] * Only expose cancellation while the withdrawal is still pending or otherwise cancellable. * Refresh the withdrawal detail or listing after cancellation to reconcile the final state. * Keep Cobru's withdrawal identifier available in your own operations tooling. --- # Withdraw cash Locale: en URL: https://docs.cobru.co/en/docs/api/cash-withdrawals/create This contract is based on legacy Cobru materials for Efecty withdrawals. Validate the provider name, callback behavior, and final error contract in sandbox before relying on it in production. Endpoint [#endpoint] `POST /cashwithdraw/` Request fields [#request-fields] | Field | Type | Required | Notes | | ---------- | --------- | -------- | ------------------------------------------------------------------- | | `method` | `string` | yes | Best-known provider selector. Legacy materials document `efecty`. | | `document` | `string` | yes | Recipient document number. | | `amount` | `number` | yes | Requested payout amount. | | `exp_days` | `number` | yes | Days until the withdrawal expires. | | `name` | `string` | yes | Recipient full name shown in the payout request. | | `coupon` | `string` | no | Optional coupon or promo code when supported. | | `callback` | `string` | no | Optional callback URL for result updates. | | `estimate` | `boolean` | no | When `true`, may request an estimate rather than a live withdrawal. | Example body [#example-body] ```json { "amount": 10000, "document": "213232323", "estimate": false, "exp_days": 30, "method": "efecty", "name": "Testeo efecty" } ``` Example response [#example-response] ```json { "status": "ok", "document": "213232323", "ref": 123456, "amount": 9700 } ``` Callback behavior [#callback-behavior] Legacy materials show a `callback` field on creation and list records. Treat callback delivery as an optional operational integration until Cobru confirms: * retry behavior * signature or verification model * terminal states that trigger callbacks Error signals seen in older materials [#error-signals-seen-in-older-materials] | Response | Meaning | | ------------------------------------ | ------------------------------------------------ | | `400 {"error":"not enough balance"}` | The sender balance is insufficient. | | `200 {"error":"BAD_USER"}` | User validation failed. | | `200 {"error":"EXPIRED"}` | Coupon or promotional benefit expired. | | `200 {"error":"ALL_USED"}` | Coupon or benefit already exhausted. | | `200 {"error":"NOT_FOUND"}` | Referenced coupon or object was not found. | | `400 {"message":"unknown method"}` | Unsupported withdrawal provider or method value. | Production notes [#production-notes] * Reconcile the net amount returned by Cobru, not only the requested amount, because fees may affect the final payout amount. * Do not assume every created withdrawal is immediately claimable; build for asynchronous provider behavior. * If you expose cancellation, store Cobru's reference identifiers at creation time. --- # Withdrawal details Locale: en URL: https://docs.cobru.co/en/docs/api/cash-withdrawals/details Legacy materials and product captures indicate a detail view for cash withdrawals, but the exact detail contract still needs fresh verification. Endpoint [#endpoint] `GET /cashwithdraw/{id}` Path parameter [#path-parameter] | Field | Type | Description | | ----- | -------- | -------------------------------------------------------------------------------- | | `id` | `number` | Cobru cash-withdrawal identifier, usually surfaced as `pk` in listing responses. | Expected use [#expected-use] * fetch the latest payout state before showing pickup instructions * support cancellation checks before calling the cancel endpoint * inspect provider-specific references when support needs to debug a payout --- # Cash withdrawals Locale: en URL: https://docs.cobru.co/en/docs/api/cash-withdrawals The cash-withdrawal family is mostly documented from legacy Cobru materials. The Efecty flow is the best-known public contract, but you should re-verify provider coverage, cancellation windows, and callback behavior before rolling it out. Cobru exposes a cash-withdrawal flow under `Retiros en efectivo`. This family is useful when you need a payout option that does not depend on a destination bank account. When to use cash withdrawals [#when-to-use-cash-withdrawals] * cash pickup payouts for recipients without bank accounts * assisted support or operations disbursements * fallback payout experiences when bank rails are unavailable Endpoints [#endpoints] | Endpoint | Method | Path | Status | | ------------------ | ------ | ---------------------- | --------------------------------- | | Withdraw cash | `POST` | `/cashwithdraw/` | documented in legacy materials | | List withdrawals | `GET` | `/cashwithdraw/` | documented in legacy materials | | Withdrawal details | `GET` | `/cashwithdraw/{id}` | legacy materials and product menu | | Cancel withdrawal | `POST` | `/cancelcashwithdraw/` | documented in legacy materials | Withdrawal lifecycle [#withdrawal-lifecycle] Create the withdrawal with recipient identity, amount, provider method, and expiration settings. Track the withdrawal from the listing or detail endpoint until it reaches a terminal state such as paid, rejected, or expired. Cancel the withdrawal before pickup when the business flow or customer request requires it and the payout is still cancellable. Known constraints [#known-constraints] * Public examples are centered on `efecty`. * Legacy materials describe callback support, but the exact webhook-style delivery contract still needs fresh validation. * State semantics exist in older exports, but they should be confirmed against a live environment before you encode business rules around them. --- # List withdrawals Locale: en URL: https://docs.cobru.co/en/docs/api/cash-withdrawals/list This listing is documented from legacy Cobru materials, but filters and pagination should still be verified live. Endpoint [#endpoint] `GET /cashwithdraw/` Fields seen in legacy responses [#fields-seen-in-legacy-responses] | Field | Type | Notes | | ----------------- | -------- | ------------------------------------------------------ | | `amount` | `number` | Requested withdrawal amount. | | `date` | `string` | Creation or provider timestamp. | | `from_user` | `string` | Source user identifier. | | `from_user_phone` | `string` | Sender phone number. | | `pk` | `number` | Cobru withdrawal identifier. | | `to_user` | `string` | Recipient descriptor or recipient name. | | `method` | `string` | Provider name such as `efecty`. | | `state` | `number` | Withdrawal state code. | | `callback` | `string` | Callback URL associated with the request when present. | State model seen in older exports [#state-model-seen-in-older-exports] | State | Meaning | | ----- | ---------- | | `0` | pending | | `1` | processing | | `2` | paid | | `3` | rejected | | `4` | cancelled | | `5` | expired | --- # Celo Locale: en URL: https://docs.cobru.co/en/docs/api/celo Celo support is documented from legacy Spotlight materials and should be treated as an advanced or beta capability until re-verified. What Cobru exposes [#what-cobru-exposes] The original Cobru materials describe a Celo / cUSD surface with these operations: * create or retrieve a wallet with `GET /celo/` * transfer cUSD with `POST /celo/` * retrieve account export details with `POST /celo/account/` * list wallet transactions with `GET /celo/transactions/cusd/` * estimate or purchase cUSD in related helper flows Recommended audience [#recommended-audience] Only ship against this surface if your product explicitly needs: * blockchain settlement visibility * cUSD treasury operations * wallet-level transfers between Cobru-managed accounts For standard checkout, PSE, BRE-B, or QR experiences, stay on Cobrus first. Example: get or create the wallet [#example-get-or-create-the-wallet] ```bash curl -X GET https://dev.cobru.co/celo/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Authorization: Bearer $COBRU_ACCESS_TOKEN" ``` ```ts const response = await fetch('https://dev.cobru.co/celo/', { method: 'GET', headers: { 'x-api-key': process.env.COBRU_API_KEY!, Authorization: `Bearer ${accessToken}`, }, }); const wallet = await response.json(); console.log(wallet.address, wallet.balance); ``` ```python import requests response = requests.get( "https://dev.cobru.co/celo/", headers={ "x-api-key": COBRU_API_KEY, "Authorization": f"Bearer {access_token}", }, ) print(response.json()) ``` ```php request('GET', 'https://dev.cobru.co/celo/', [ 'headers' => [ 'x-api-key' => getenv('COBRU_API_KEY'), 'Authorization' => 'Bearer ' . $accessToken, ], ]); $wallet = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR); var_dump($wallet); ``` Operational warnings [#operational-warnings] The legacy docs mention a flow that returns the 24-word mnemonic for wallet recovery. Treat that as extremely sensitive material. Do not log it, persist it casually, or expose it to customer support tools. The historical docs mention Alfarojes and mainnet explorers. Confirm chain, explorer, and environment behavior before exposing any user-facing transaction explorer link. If you support cUSD, create operational runbooks for wallet export, transfer failure recovery, and finance reconciliation before enabling it for customers. Related docs [#related-docs] Inspect the Celo endpoints and schemas in the interactive reference. Design treasury and balance workflows around the broader Cobru account model. --- # Botón Bancolombia Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/bancolombia-button Endpoint [#endpoint] `POST /{url}` Request [#request] ```json { "name": "Test Gómez", "payment": "bancolombia_transfer", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC" } ``` Next step [#next-step] Spotlight says the response contains a `checkout` URL that the user must open to complete the payment. --- # Bre-B Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/breb Endpoint [#endpoint] `POST /{url}` Request [#request] ```json { "payment": "breb" } ``` This is the most minimal payment-details variant documented in Spotlight. Spotlight documents direct `payment: "breb"`, but later sandbox research observed this path as commercially gated or disabled in some environments. Confirm direct Bre-B availability in your own sandbox before treating it as production-ready. What to expect back [#what-to-expect-back] Spotlight shows a payment-order response that includes: * `qr_value` * `key_value` * `method: "breb"` * `franchise: "breb"` The original materials also state that both `qr_value` and `key_value` expire after 5 minutes. When to use it [#when-to-use-it] Use Bre-B when you want an interoperable bank-transfer option and your product can work with short-lived payment instructions plus webhook-based confirmation. --- # Cash payments Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/cash-payments Endpoint [#endpoint] `POST /{url}` Supported payment literals [#supported-payment-literals] * `efecty` * `corresponsal_bancolombia` Spotlight also mentions cash rails such as Baloto in older examples, but the clearest request examples are for Efecty and Corresponsal Bancolombia. Request example [#request-example] ```json { "name": "Juan Perez", "payment": "efecty", "cc": "1140867070", "email": "juan@cobru.co", "document_type": "CC", "phone": "3002794981" } ``` The request shape for `corresponsal_bancolombia` is the same, changing only the `payment` literal. --- # Consult a cobru Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/consult Endpoint [#endpoint] `GET /cobru_detail/{url}` This endpoint is documented in legacy Cobru materials. It was previously believed to be unavailable, so re-verify it in your own sandbox account before using it as a critical dependency. Response fields observed in legacy documentation [#response-fields-observed-in-legacy-documentation] * payer identity fields * `payment_method` * `state` * `payment_method_enabled` * `amount` * `description` * `payed_amount` * fee and date fields Example response [#example-response] ```json { "fee_amount": 6383, "payer_id": "10000000", "payer_name": "Juan Plata", "payment_method": "efecty", "state": 1, "payer_email": "juan@cobru.com", "url": "ufa8q176", "amount": 107595, "description": "description", "payed_amount": 100000 } ``` --- # Create a cobru Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/create Endpoint [#endpoint] `POST /cobru/` Verified in sandbox. This is the best-documented and most production-ready Cobru flow today. Required fields [#required-fields] ```json { "amount": 50000, "description": "Order #123", "expiration_days": 1, "client_assume_costs": false, "iva": 0, "payment_method_enabled": "{\"breb\":true,\"pse\":true,\"NEQUI\":true}", "payer_redirect_url": "https://yourapp.com/payment-success", "callback": "https://yourapp.com/api/cobru/webhook" } ``` Known quirks [#known-quirks] | Quirk | Detail | Fix | | ----------------------------- | ------------------------ | ----------------------------------------------- | | `payment_method_enabled` type | must be a JSON string | use `JSON.stringify()` | | missing redirect URLs | returns misleading `403` | always send `payer_redirect_url` and `callback` | | response `url` | short slug only | build `{baseUrl}/{url}` yourself | | response `amount` | string with decimals | parse before doing math | Common payment method flags [#common-payment-method-flags] ```json { "cobru": true, "pse": true, "bancolombia_transfer": true, "credit_card": true, "NEQUI": true, "dale": true, "efecty": true, "corresponsal_bancolombia": true, "BTC": false, "CUSD": false } ``` Response example [#response-example] ```json { "pk": 27150, "amount": "50000.00", "state": 0, "url": "3gofdf6f", "payed_amount": "47605.00", "fee_amount": 2395, "idempotency_key": "3114242222_8de7c88b84...", "currency_code": "COP" } ``` curl [#curl] ```bash curl -X POST https://dev.cobru.co/cobru/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Authorization: Bearer $COBRU_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "amount": 50000, "description": "Order #123", "expiration_days": 1, "client_assume_costs": false, "iva": 0, "payment_method_enabled": "{\"breb\":true,\"pse\":true}", "payer_redirect_url": "https://yourapp.com/payment-success", "callback": "https://yourapp.com/api/cobru/webhook" }' ``` --- # Credit card Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/credit-card Endpoint [#endpoint] `POST /{url}` Request [#request] ```json { "name": "Test Gómez", "payment": "credit_card", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC", "credit_card": "4111111111111111", "expiration_date": "12/30", "cvv": "123", "dues": 1 } ``` Spotlight notes [#spotlight-notes] * Cobru does not store card data * production traffic must be HTTPS * test cards shown by Spotlight: * approved: `4111 1111 1111 1111` * declined: `4111 1111 1111 1112` --- # dale! Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/dale Endpoint [#endpoint] `POST /{url}` Request [#request] ```json { "name": "Test Gómez", "payment": "dale", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC" } ``` --- # Daviplata Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/daviplata Step 1 — Start the payment [#step-1--start-the-payment] `POST /{url}` ```json { "name": "Test Gómez", "payment": "daviplata", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC" } ``` Step 2 — Confirm the OTP [#step-2--confirm-the-otp] Spotlight documents a follow-up endpoint: `POST /cobru/confirm_daviplata/` ```json { "URL": "ufa8q176", "OTP": "123456" } ``` If everything succeeds, Spotlight describes a response with `result == "OK"`. Cobru has not yet published a full OTP replay for this step in the sandbox evidence that backs this repo. Treat the endpoint as a strong legacy contract, not as a freshly verified live flow. --- # Edit a cobru Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/edit Endpoint [#endpoint] `POST /edit_cobru/` Documented in legacy Cobru materials. Verify in sandbox which fields remain editable after a payment has been shared or partially used. Fields seen in legacy documentation [#fields-seen-in-legacy-documentation] | Field | Required | Purpose | | ----------------- | -------- | -------------------------- | | `url` | yes | identify the cobru to edit | | `description` | no | update the description | | `amount` | no | change the amount | | `expiration_days` | no | change expiration | | `payment_methods` | no | update allowed methods | | `fee_iva` | no | update tax percentage | Example request [#example-request] ```json { "url": "xx17elpi", "description": "updated description", "amount": 80000, "expiration_days": 10 } ``` --- # Cobrus Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus A "cobru" is Cobru's hosted payment object. It combines amount, description, enabled payment methods, expiration, redirect URLs, and the callback that reports payment state changes. Start here [#start-here] Recommended reading order [#recommended-reading-order] 1. [Create a cobru](/en/docs/api/cobrus/create) 2. [Submit payment details](/en/docs/api/cobrus/payment-details) 3. Method-specific pages such as [Bre-B](/en/docs/api/cobrus/breb), [PSE](/en/docs/api/cobrus/pse), and [Nequi](/en/docs/api/cobrus/nequi) 4. [Consult a cobru](/en/docs/api/cobrus/consult) 5. [Quote a cobru](/en/docs/api/cobrus/quote) or [Edit a cobru](/en/docs/api/cobrus/edit) only if your product needs those flows Endpoint map [#endpoint-map] | Endpoint family | Method | Verification status | | ------------------------ | ------ | ------------------------------------ | | Create a cobru | `POST` | verified | | Generate payment details | `POST` | documented in legacy Cobru materials | | Consult a cobru | `GET` | documented in legacy Cobru materials | | PSE banks | `GET` | documented in legacy Cobru materials | | Quote a cobru | `POST` | documented in legacy Cobru materials | | Edit a cobru | `POST` | documented in legacy Cobru materials | Common state values [#common-state-values] | State | Meaning | | ----- | ------------------- | | `0` | Created | | `1` | In process | | `2` | Not paid / rejected | | `3` | Paid | | `4` | Refunded | | `5` | Expired | Operational notes [#operational-notes] * Treat payment creation and final payment state as separate moments in your system. * Store Cobru's `url`, `pk`, and your own internal order identifier together from the first write. * If a method-specific flow is not freshly verified, keep it behind an explicit operational review before broad rollout. --- # Nequi Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/nequi Endpoint [#endpoint] `POST /{url}` Request [#request] ```json { "name": "Test Gómez", "payment": "NEQUI", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC", "phone_nequi": "307654332", "push": true } ``` Push behavior [#push-behavior] * `push: true` sends a push request to the payer's Nequi app * `push: false` avoids the push and Spotlight says the response includes the data required to generate a QR-style experience, including `ref` --- # Submit payment details Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/payment-details Endpoint [#endpoint] `POST /{url}` This contract comes primarily from Cobru's original Spotlight materials, compiled internal API notes, and later checkout research. Cobru has not yet replayed every method variant end-to-end in this repo's published sandbox evidence, so keep this endpoint in the `legacy-doc` bucket for production planning. Confidence by method [#confidence-by-method] | Method | Confidence | Why | | ---------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `pse` | higher | multiple sources agree on `bank` plus the dependency on `GET /get_banks/1/` | | `NEQUI` | medium | request shape is consistent across Spotlight and later research, but runtime still varies with payer data | | `daviplata` | medium | both Spotlight and later research document the OTP follow-up, but Cobru has not yet published a full confirmed OTP replay in this repo | | `credit_card` | medium | Spotlight provides a clear payload and test cards, but live production parity still needs re-validation | | `breb` | medium-low | Spotlight documents direct `payment: "breb"`, but later sandbox research observed this path as commercially gated or disabled | | cash and agent methods | medium-low | payloads are documented, but response details are still mostly legacy-derived | Purpose [#purpose] After a cobru exists, this endpoint receives the payer details and the fields required by the selected payment method. This is the checkout hub for: * Bre-B * PSE * Efecty and Corresponsal Bancolombia * Nequi * dale! * Botón Bancolombia * Daviplata * credit cards Path parameter [#path-parameter] | Field | Type | Description | | ----- | ------ | ----------------------------------------- | | `url` | string | the cobru slug returned by `POST /cobru/` | Common fields [#common-fields] ```json { "name": "Juan Perez", "payment": "efecty", "cc": "1140867070", "email": "juan@cobru.co", "document_type": "CC", "phone": "3002794981" } ``` | Field | Required | Notes | | --------------- | -------------------- | --------------------------------------------- | | `name` | yes for most methods | payer name | | `payment` | yes | payment method selector | | `cc` | yes for most methods | payer document number | | `email` | yes for most methods | payer email | | `document_type` | yes for most methods | Spotlight shows `CC`, `TI`, `CE`, `NIT`, `PA` | | `phone` | yes for most methods | payer phone | Use the field name `payment`, not `payment_method`. Spotlight and later research both point to `payment` as the accepted selector. Response and error behavior seen in Spotlight [#response-and-error-behavior-seen-in-spotlight] | Status | Cause | Notes | | ------ | ----------------------------------------------- | ------------------------------------------------------------------- | | `200` | payment details generated | response shape varies by method | | `403` | trying to pay your own cobru with Cobru balance | Spotlight shows `{"result":"same_user"}` | | `400` | owner would exceed allowed balance | `{"result":"LIMIT_BALANCE"}` | | `400` | cobru already paid | `{"result":"COBRU_IS_PAYED"}` | | `400` | unknown payment method | `{"error": true, "msg": "unknown payment method"}` | | `400` | method not enabled | `{"error":"Payment method is not enabled.","result":"NOT_ALLOWED"}` | | `404` | Cobru-balance payer not found | legacy flow only | Method matrix [#method-matrix] | Method | `payment` literal | Extra fields | Next step | | ------------------------ | -------------------------- | ----------------------------------------------- | -------------------------------------- | | Bre-B | `breb` | none in the base request | render `qr_value` / `key_value` | | PSE | `pse` | `bank`, `address` | redirect to PSE URL returned by Cobru | | Efecty | `efecty` | none beyond common fields | show the cash payment details returned | | Corresponsal Bancolombia | `corresponsal_bancolombia` | none beyond common fields | show the payment details returned | | Nequi | `NEQUI` | `phone_nequi`, optional `push` | use `checkout` or QR-style response | | dale! | `dale` | none beyond common fields | follow the response returned by Cobru | | Botón Bancolombia | `bancolombia_transfer` | none beyond common fields | redirect to `checkout` | | Daviplata | `daviplata` | none in the first request | confirm later with OTP | | Credit card | `credit_card` | `credit_card`, `expiration_date`, `cvv`, `dues` | complete card payment flow | Bre-B [#bre-b] ```json { "payment": "breb" } ``` Spotlight shows a response that includes: * `qr_value` * `key_value` * `method: "breb"` * `franchise: "breb"` The original materials also state that `qr_value` and `key_value` live for 5 minutes. Later sandbox research observed direct `payment: "breb"` as commercially gated or disabled in some environments. Treat the request shape as documented, but do not assume direct Bre-B availability without your own sandbox confirmation. PSE [#pse] PSE requires two extra fields: | Field | Type | Description | | --------- | ------ | ----------------- | | `bank` | string | numeric bank code | | `address` | string | payer address | ```json { "name": "Juan Perez", "payment": "pse", "cc": "1140867070", "email": "juan@cobru.co", "document_type": "CC", "phone": "300000000", "bank": "1040", "address": "Bogotá, Colombia" } ``` Before sending `payment: "pse"`, fetch the available bank list from `GET /get_banks/1/` and send the selected `bankCode` in the `bank` field. Among the legacy checkout variants, PSE is one of the best corroborated flows in Cobru's materials because the bank dependency, request fields, and redirect pattern line up across multiple sources. If the request succeeds, Cobru returns the PSE URL that your frontend should use to redirect the user. Cash methods: Efecty and Corresponsal Bancolombia [#cash-methods-efecty-and-corresponsal-bancolombia] Spotlight groups these as cash-style payment detail generation. ```json { "name": "Juan Perez", "payment": "efecty", "cc": "1140867070", "email": "juan@cobru.co", "document_type": "CC", "phone": "3002794981" } ``` `corresponsal_bancolombia` uses the same common-field shape, only changing the `payment` literal. Nequi [#nequi] ```json { "name": "Test Gómez", "payment": "NEQUI", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC", "phone_nequi": "307654332", "push": true } ``` Behavior described by Spotlight: * `push: true` triggers a push in the user's Nequi app * `push: false` avoids the push and returns the data needed to generate a QR-style experience, including `ref` dale! [#dale] ```json { "name": "Test Gómez", "payment": "dale", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC" } ``` Botón Bancolombia [#botón-bancolombia] ```json { "name": "Test Gómez", "payment": "bancolombia_transfer", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC" } ``` Spotlight says the response includes a `checkout` URL that the user should open to complete the payment. Daviplata [#daviplata] Initial request: ```json { "name": "Test Gómez", "payment": "daviplata", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC" } ``` After the payer receives the Daviplata OTP, Spotlight requires a second call: `POST /cobru/confirm_daviplata/` Body fields: | Field | Description | | ----- | ------------------------- | | `URL` | cobru URL/slug | | `OTP` | OTP received by the payer | Success is described as `result == "OK"`. Cobru has not yet published a full Daviplata OTP replay in this repo's sandbox evidence. Use this contract as a strong legacy reference, but confirm the exact request/response behavior before shipping a production dependency on it. Credit card [#credit-card] ```json { "name": "Test Gómez", "payment": "credit_card", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC", "credit_card": "4111111111111111", "expiration_date": "12/30", "cvv": "123", "dues": 1 } ``` Spotlight notes: * Cobru does not persist card data * production traffic must be HTTPS * test cards shown in Spotlight: * approved: `4111 1111 1111 1111` * declined: `4111 1111 1111 1112` Related pages [#related-pages] * [Bre-B payment flow](/en/docs/guides/qr-breb) * [Bre-B](/en/docs/api/cobrus/breb) * [PSE payments](/en/docs/api/cobrus/pse) * [Cash payments](/en/docs/api/cobrus/cash-payments) * [Nequi](/en/docs/api/cobrus/nequi) * [Daviplata](/en/docs/api/cobrus/daviplata) --- # PSE bank codes Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/pse-banks Endpoint [#endpoint] `GET /get_banks/1/` This endpoint appears in legacy Cobru materials and is a common dependency when presenting PSE options to users. Example response [#example-response] ```json [ { "bankName": "BANCO AGRARIO", "bankCode": "1040" }, { "bankName": "BANCO AV VILLAS", "bankCode": "1052" }, { "bankName": "BANCO BBVA COLOMBIA S.A.", "bankCode": "1013" } ] ``` --- # PSE payments Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/pse Endpoint [#endpoint] `POST /{url}` Required dependency [#required-dependency] Before calling the payment-details endpoint with PSE, fetch the bank catalog from: `GET /get_banks/1/` Use the selected `bankCode` in the `bank` field. PSE is one of the most corroborated legacy checkout flows in Cobru's materials. The bank dependency, request shape, and redirect pattern line up across Spotlight, compiled API notes, and later checkout research. Request [#request] ```json { "name": "Juan Perez", "payment": "pse", "cc": "1140867070", "email": "juan@cobru.co", "document_type": "CC", "phone": "300000000", "bank": "1040", "address": "Bogotá, Colombia" } ``` Next step [#next-step] If the request succeeds, Cobru returns the PSE URL that your frontend should use to redirect the user. --- # Quote a cobru Locale: en URL: https://docs.cobru.co/en/docs/api/cobrus/quote Endpoint [#endpoint] `POST /cobru/estimate/` Documented in legacy Cobru materials. Useful for cart previews and merchant-side fee estimation. Example request [#example-request] ```json { "amount": "5000", "client_assume_costs": true } ``` Example response [#example-response] ```json { "cobru_amount": 5000, "cobru_fee": 295, "iva": 56.05, "cobru_payed_amount": 4700 } ``` --- # Transfers Locale: en URL: https://docs.cobru.co/en/docs/api/envios This family is documented from legacy Cobru materials and menu captures. Re-verify paths, filters, and balance movement side effects in sandbox before depending on it for production-critical payout flows. Cobru's transfer surface appears under `Envios` in the product API menu. It is the best-known way to move available Cobru balance from one Cobru user to another without opening a bank withdrawal flow. When to use transfers [#when-to-use-transfers] * move balance between Cobru-operated accounts * trigger support, operations, or wallet-to-wallet disbursement flows * build a lightweight internal transfer experience before you need bank rails Authentication [#authentication] Transfers are documented as authenticated user operations. Treat them as balance-sensitive endpoints and require a valid Cobru session or token before calling them. Endpoints [#endpoints] | Endpoint | Method | Path | Status | | -------------------------- | ------ | -------- | ------------------------------ | | Send money to another user | `POST` | `/send/` | documented in legacy materials | | List your transfers | `GET` | `/send/` | documented in legacy materials | Transfer lifecycle [#transfer-lifecycle] Confirm the sender account is fully usable. Legacy Cobru materials say the sender must have verified email and phone before sending balance. Send balance to another Cobru user using the recipient's phone number as the best-known identifier. Reconcile transfer history from the transfer listing endpoint before showing final operational state in a dashboard or support panel. Known constraints [#known-constraints] * Recipient identity is documented as a phone-based identifier. * Public materials do not yet confirm idempotency, pagination, or explicit transfer status fields. * If your business flow needs bank settlement, use bank withdrawals instead of `Envios`. --- # List transfers Locale: en URL: https://docs.cobru.co/en/docs/api/envios/list This endpoint is documented from legacy Cobru materials, but filters and pagination still need fresh verification from a live Cobru environment. Endpoint [#endpoint] `GET /send/` Response fields seen in legacy materials [#response-fields-seen-in-legacy-materials] | Field | Type | Notes | | ----------- | -------- | ---------------------------------------------------- | | `from_user` | `string` | Sender identifier. | | `to_user` | `string` | Recipient identifier. | | `amount` | `number` | Transfer amount. | | `date` | `string` | Transfer creation timestamp or formatted date field. | How to use the listing [#how-to-use-the-listing] * reconcile outbound transfers in an operations panel * confirm whether a send request has already been registered * build customer-support tooling around wallet-to-wallet movement What still needs confirmation [#what-still-needs-confirmation] * pagination fields * available filters * whether the list includes transfer status or only the core ledger record --- # Send money Locale: en URL: https://docs.cobru.co/en/docs/api/envios/send This contract comes from legacy Cobru materials. Re-verify the exact request and response payload in sandbox before using it in a production transfer workflow. Endpoint [#endpoint] `POST /send/` Requirements [#requirements] * the sender must have verified email and phone * the recipient is identified by phone number Request fields [#request-fields] | Field | Type | Required | Notes | | --------- | -------- | -------- | -------------------------------------------------------------------------------------------- | | `to_user` | `string` | yes | Best-known recipient identifier. Legacy materials describe it as the recipient phone number. | | `amount` | `number` | yes | Amount to send from the authenticated Cobru user's available balance. | Some older prose references `toUser` in camelCase. Prefer `to_user` unless Cobru confirms a second accepted alias. Example body [#example-body] ```json { "amount": 99000, "to_user": "3001234567" } ``` Production notes [#production-notes] * Validate sender KYC and account readiness before exposing this action in UI. * The public materials do not confirm whether transfers are synchronous, queued, or reversible. * Treat transfer success as untrusted until you can reconcile it through `GET /send/` or a downstream ledger. --- # API Reference Locale: en URL: https://docs.cobru.co/en/docs/api/reference --- # Cell phone recharge Locale: en URL: https://docs.cobru.co/en/docs/api/services/cell-recharge This recharge flow is documented from legacy Cobru exports. Supported operators and response payloads should still be re-verified before production use. Endpoint [#endpoint] `POST /request_service_reload/` Request fields seen in legacy documentation [#request-fields-seen-in-legacy-documentation] | Field | Type | Required | Notes | | ----------- | -------- | -------- | ----------------------------------------------- | | `value` | `number` | yes | Recharge amount. | | `recipient` | `string` | yes | Target phone number. | | `operator` | `string` | yes | Mobile operator code or name expected by Cobru. | Response fields seen in older docs [#response-fields-seen-in-older-docs] | Field | Type | Notes | | --------- | -------- | -------------------------- | | `result` | `string` | Recharge outcome. | | `message` | `string` | Provider or Cobru message. | Supported operators seen in legacy materials [#supported-operators-seen-in-legacy-materials] Older exports mention operators such as `claro`, `movistar`, `tigo`, and `avantel`. Treat that list as indicative until you confirm the current live catalog. --- # Digital services Locale: en URL: https://docs.cobru.co/en/docs/api/services The services family is documented from legacy Cobru exports and product-menu visibility. The overall capability is clear, but you should still verify inventory behavior and fulfillment responses before go-live. Cobru's API menu exposes a `Servicios` section for digital products. These endpoints are useful when Cobru is acting as a digital-goods distribution surface in addition to a payments API. Choose a service workflow [#choose-a-service-workflow] Visible capabilities [#visible-capabilities] | Capability | Method | Path | Confidence | | --------------------- | ------ | -------------------------- | ---------- | | Cell phone recharge | `POST` | `/request_service_reload/` | legacy-doc | | PIN products list | `GET` | `/pines/all_pines/` | legacy-doc | | PIN purchase | `POST` | `/pin/` | legacy-doc | | Data packages list | `GET` | `/packages/all_packages/` | legacy-doc | | Data package purchase | `POST` | `/packages/buy/` | legacy-doc | Service workflow [#service-workflow] Fetch catalog or operator data before presenting an offer to the end user. Create the recharge, PIN purchase, or package purchase with the expected provider fields. Reconcile fulfillment result and inventory availability before confirming success to the customer. --- # Buy PINs Locale: en URL: https://docs.cobru.co/en/docs/api/services/pins-buy This purchase flow is documented from legacy Cobru exports. Confirm inventory rules and the final fulfillment payload before production use. Endpoint [#endpoint] `POST /pin/` Request fields seen in legacy documentation [#request-fields-seen-in-legacy-documentation] | Field | Type | Required | Notes | | ---------- | -------- | -------- | -------------------------------------- | | `id_pin` | `number` | yes | Catalog identifier of the PIN product. | | `operator` | `string` | yes | Provider or operator identifier. | Response fields seen in older docs [#response-fields-seen-in-older-docs] | Field | Type | Notes | | -------- | -------- | --------------------------------- | | `status` | `string` | Purchase result. | | `pin` | `string` | Delivered PIN or redemption code. | | `pk` | `number` | Cobru purchase identifier. | --- # PIN products list Locale: en URL: https://docs.cobru.co/en/docs/api/services/pins-list This catalog endpoint is documented from legacy Cobru exports. Verify filtering and catalog schema in a live environment before relying on it. Endpoint [#endpoint] `GET /pines/all_pines/` Optional query variant seen in older docs [#optional-query-variant-seen-in-older-docs] `GET /pines/all_pines/?operator={operator}` Use the operator-scoped variant when you want to pre-filter the PIN catalog for a specific provider. --- # Tokenization Locale: en URL: https://docs.cobru.co/en/docs/api/tokenization This surface comes from Cobru legacy materials and still needs fresh sandbox verification. Treat it as a beta contract until the official OpenAPI export or a new validation pass confirms each field. What this capability is for [#what-this-capability-is-for] Use tokenization when your integration needs to: * register a card once and charge it later * avoid collecting raw PAN details on every payment flow * list saved cards for the authenticated account * remove card-on-file records when the user requests it Cobru flow [#cobru-flow] Fetch Cobru's RSA public key from `GET /base/get_constants_key_public/`. Encrypt sensitive card fields client-side or in a PCI-scoped service. Register the card with `POST /register_tc/`. Retrieve cards with `GET /list_tc/` and charge a saved instrument with `POST /tc_payment/`. Endpoint map [#endpoint-map] | Endpoint | Purpose | Status | | ------------------------------------- | ---------------------------------------------- | ---------- | | `GET /base/get_constants_key_public/` | Retrieve the RSA public key | Legacy doc | | `POST /register_tc/` | Register a credit card token | Legacy doc | | `GET /list_tc/` | List saved cards or inspect one by `card_uuid` | Legacy doc | | `POST /tc_payment/` | Pay with a saved or tokenized card | Legacy doc | | `DELETE /delete_tc/` | Remove a stored card | Legacy doc | Authentication model [#authentication-model] Cobru's Spotlight exports suggest the tokenization endpoints are authenticated user surfaces. Until sandbox verification is complete, assume: * standard Cobru auth headers still apply * requests must originate from trusted backend or PCI-scoped services * `x-api-key` never belongs in public frontend code Example: fetch the public key [#example-fetch-the-public-key] ```bash curl -X GET https://dev.cobru.co/base/get_constants_key_public/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Authorization: Bearer $COBRU_ACCESS_TOKEN" ``` ```ts const response = await fetch('https://dev.cobru.co/base/get_constants_key_public/', { method: 'GET', headers: { 'x-api-key': process.env.COBRU_API_KEY!, Authorization: `Bearer ${accessToken}`, }, }); const payload = await response.json(); console.log(payload.data.text_long_value); ``` ```python import requests response = requests.get( "https://dev.cobru.co/base/get_constants_key_public/", headers={ "x-api-key": COBRU_API_KEY, "Authorization": f"Bearer {access_token}", }, ) print(response.json()) ``` ```php request('GET', 'https://dev.cobru.co/base/get_constants_key_public/', [ 'headers' => [ 'x-api-key' => getenv('COBRU_API_KEY'), 'Authorization' => 'Bearer ' . $accessToken, ], ]); $payload = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR); var_dump($payload); ``` Operational notes [#operational-notes] Cobru's legacy flow expects RSA encryption of card number, cardholder name, and expiry fields. Even with tokenization, you should treat the capture UI and transport as PCI-sensitive until Cobru publishes a narrower trust model. The legacy docs reference mobile/device fields such as `imei`, `latitude`, and `longitude`. Do not hard-code those fields as universally required until a new verification pass confirms them. Use Cobru tokenization only from a backend or PCI-scoped proxy, log only masked card identifiers, and design your own delete-card recovery flow. Next steps [#next-steps] Explore the tokenization methods inside the interactive OpenAPI reference. Continue with Cobru-issued cards and post-issuance operations. --- # Changelog Locale: es URL: https://docs.cobru.co/es/docs/changelog 2026-04-09 [#2026-04-09] Refresh IA inspirado en Kapso [#refresh-ia-inspirado-en-kapso] * Cambiamos el shell a una experiencia de lectura más oscura, compacta y Kapso-like sobre Fumadocs Notebook. * Dejamos dark mode por defecto y alineamos light mode con el logo verde de Cobru. * Añadimos `Build with AI` como ruta de plataforma de primera clase para workflows con coding agents. Refresh de navegación y marca [#refresh-de-navegación-y-marca] * Reemplazamos los tabs `Docs / API / Guides` por una navbar orientada a producto. * Reorganizamos la sidebar alrededor de `Payments`, `Payouts`, `Platform` y `Changelog`. * Hicimos más visible el verde de Cobru en active states, iconos y acentos de sección. Nuevos hubs públicos [#nuevos-hubs-públicos] * Añadimos páginas dedicadas para `Payouts`, `Platform` y `Changelog`. * Mantuvimos Notebook Layout y primitives de Fumadocs como base del shell. 2026-04-08 [#2026-04-08] Documentación de métodos de checkout [#documentación-de-métodos-de-checkout] * Reescribimos Bre-B y `submitPaymentDetails` a partir de exports de Spotlight. * Añadimos páginas por método para PSE, Nequi, dale!, Daviplata, tarjeta, pagos en efectivo y Botón Bancolombia. * Agregamos `confirmDaviplataPayment` a la fuente OpenAPI. Estabilización de la referencia API [#estabilización-de-la-referencia-api] * Corregimos el problema runtime de producción que afectaba `/docs/api/reference/**`. * Añadimos smoke coverage para la referencia API y para rutas narrativas críticas de Cobrus. 2026-04-07 [#2026-04-07] Plataforma repo-first [#plataforma-repo-first] * Migramos el contrato OpenAPI a una fuente multi-file propia del repo en `openapi/src/**`. * Añadimos checks de gobernanza para localization sync, validación OpenAPI y smoke tests de rutas críticas. * Expandimos la superficie bilingüe para payouts, services, cards, tokenization y Celo. --- # Payouts Locale: es URL: https://docs.cobru.co/es/docs/payouts La superficie de payouts de Cobru cubre envíos entre usuarios Cobru, retiros en efectivo, retiros bancarios y la visibilidad operativa que los equipos necesitan para conciliar movimientos salientes. Elige un flujo de salida [#elige-un-flujo-de-salida] Orden recomendado [#orden-recomendado] 1. Revisa [Envíos](/es/docs/api/envios) si los fondos se quedan dentro del ecosistema Cobru. 2. Usa [Retiros en efectivo](/es/docs/api/cash-withdrawals) para operaciones payout-to-cash. 3. Usa [Retiros bancarios](/es/docs/api/bank-withdrawals) para settlement bancario y flujos de transferencia Bre-B. 4. Cierra con [Balances](/es/docs/guides/balances) y [Movimientos](/es/docs/guides/movements) para endurecer conciliación. Musts operativos [#musts-operativos] * Trata las operaciones de payout como asíncronas hasta que tu propio sistema confirme el estado final. * Conserva juntos los identificadores de Cobru y tus propias llaves de conciliación desde la primera escritura. * Usa las notificaciones webhook como triggers y tu lógica de consulta como fuente de verdad para movimientos de dinero sensibles. --- # Platform Locale: es URL: https://docs.cobru.co/es/docs/platform Usa la capa de plataforma para iniciar integraciones, verificar contratos, endurecer el comportamiento operativo y dar a los agentes de IA una manera confiable de consumir la documentación de Cobru. Elige una ruta de plataforma [#elige-una-ruta-de-plataforma] Checklist de plataforma [#checklist-de-plataforma] 1. Empieza por [Autenticación](/es/docs/authentication) para estabilizar emisión y caché de tokens. 2. Sigue con [Webhooks](/es/docs/webhooks) antes de tratar el estado de pagos como production-ready. 3. Usa [Pruebas](/es/docs/testing) y [Preparación para producción](/es/docs/production-readiness) para cerrar gaps operativos. 4. Usa [Build with AI](/es/docs/build-with-ai) si tu equipo depende de coding agents o copilots internos. 5. Abre la [Referencia API](/es/docs/api/reference) cuando necesites detalle exacto del contrato. --- # Autenticación Locale: es URL: https://docs.cobru.co/es/docs/authentication Cobru usa un modelo de autenticación por capas: * `x-api-key`: tu llave de integración * `Authorization: Bearer {access}`: token de acceso de corta duración obtenido desde `/token/refresh/` Empieza aquí [#empieza-aquí] 1. Guarda `x-api-key` y el token `refresh` solo en almacenamiento secreto backend. 2. Emite un access token desde `/token/refresh/`. 3. Cachea ese access token de forma centralizada antes de hacer llamadas rutinarias. 4. Reúsalo hasta que toque refrescarlo en lugar de emitirlo en cada request. Rol de cada credencial [#rol-de-cada-credencial] | Credencial | Dónde usarla | Notas | | --------------- | ----------------------------------- | --------------------------------------------------------------------------- | | `x-api-key` | requests backend | Trátala como credencial de integración y mantenla fuera de bundles frontend | | token `refresh` | solo almacenamiento secreto backend | Se usa únicamente para emitir access tokens temporales | | token `access` | requests backend | Cachearlo agresivamente y rotarlo con frecuencia | Flujo de refresh del token [#flujo-de-refresh-del-token] ```bash curl -X POST https://dev.cobru.co/token/refresh/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Content-Type: application/json" \ -d '{"refresh":"'"$COBRU_REFRESH_TOKEN"'"}' ``` **Respuesta esperada** ```json { "access": "eyJ0eXAi..." } ``` El campo del body es `refresh`, no `refresh_token`. Esta discrepancia es uno de los quirks más importantes de Cobru y debe quedar muy visible para el equipo. Headers requeridos para requests API [#headers-requeridos-para-requests-api] ```http x-api-key: {tu_api_key} Authorization: Bearer {access} Accept: application/json Content-Type: application/json ``` Vida útil del token y caché [#vida-útil-del-token-y-caché] | Propiedad | Recomendación | | ----------------------------- | ------------------------------------------------------------ | | vida útil observada del token | cerca de 60 minutos | | TTL seguro de caché | 50 minutos | | caveat en Edge runtime | los caches en memoria no persisten entre invocaciones | | fix de producción | guardar el token en Redis, Vercel KV u otro caché compartido | Variables de entorno [#variables-de-entorno] ```bash COBRU_BASE_URL=https://dev.cobru.co COBRU_API_KEY=... COBRU_REFRESH_TOKEN=... ``` Checklist de seguridad [#checklist-de-seguridad] * Mantén todas las credenciales Cobru solo en variables de entorno del servidor. * Nunca envíes `x-api-key` al navegador ni a clientes móviles. * Refresca el access token desde el servidor, no desde el frontend. * Rota credenciales cuando cambie el equipo con acceso. * Usa URLs `callback` con HTTPS en producción. Sigue con [#sigue-con] * `/docs/getting-started` * `/docs/webhooks` * `/docs/api/authentication/refresh` --- # Build with AI Locale: es URL: https://docs.cobru.co/es/docs/build-with-ai Cobru Docs está diseñada para funcionar tanto para developers leyendo en el navegador como para sistemas de IA que necesitan markdown estable y URLs canónicas. Qué pueden usar hoy las herramientas de IA [#qué-pueden-usar-hoy-las-herramientas-de-ia] Workflow recomendado para coding agents [#workflow-recomendado-para-coding-agents] 1. Empieza por `/llms.txt` para descubrir el camino relevante más corto. 2. Extrae el markdown narrativo antes de generar código desde memoria. 3. Pasa a `/docs/api/reference` para validar request y response shapes exactos. 4. Trata las páginas marcadas con caveats de verificación como fuentes de menor confianza. Modelo de verdad [#modelo-de-verdad] * La docs pública documenta solo comportamiento actual de Cobru o contratos legacy/menu-derived etiquetados explícitamente. * `verified`, `legacy-doc` y `menu-only` siguen siendo distinciones reales dentro del source OpenAPI. * Los webhooks no tienen hoy una firma pública documentada, así que los agentes no deben modelarlos como entradas criptográficamente confiables. Mejores páginas para combinar con IA [#mejores-páginas-para-combinar-con-ia] * [Inicio rápido](/es/docs/getting-started) * [Autenticación](/es/docs/authentication) * [Webhooks](/es/docs/webhooks) * [Preparación para producción](/es/docs/production-readiness) * [Referencia API](/es/docs/api/reference) --- # Referencia de errores Locale: es URL: https://docs.cobru.co/es/docs/errors El modelo actual de errores de Cobru funciona, pero todavía no es ergonómico. Algunas fallas de validación aparecen como `403 Forbidden`, y la forma de la respuesta no siempre es descriptiva. Formatos de respuesta actuales [#formatos-de-respuesta-actuales] Lo más común es ver una de estas respuestas: ```json { "error": "Error en la creacion del cobru." } ``` ```json { "payment_method_enabled": ["Not a valid string."] } ``` Estrategia recomendada para manejar errores [#estrategia-recomendada-para-manejar-errores] Captura el status HTTP exacto, headers y body raw de respuesta de Cobru. Normaliza la respuesta de Cobru a tu propio tipo de error interno. Decide si el error es reintentable, corregible por el caller u operativo. Muestra un mensaje seguro al usuario final y conserva el payload raw en logs. Quirks conocidos [#quirks-conocidos] | Síntoma | HTTP code | Causa real | Fix | | ------------------------------------------------ | -------------------- | --------------------------------------------- | -------------------------------------------------------------- | | `payment_method_enabled` enviado como objeto | `400` | Cobru espera un string JSON | ejecutar `JSON.stringify()` antes de enviar | | falta `payer_redirect_url` o `callback` | `403` | falla de validación del request | enviar ambos campos al crear el pago | | hay credenciales pero falla la creación del pago | `403` | la forma del body puede ser inválida, no auth | revisar `payment_method_enabled`, redirect URLs y content type | | falla el campo `refresh_token` | `400` o auth failure | nombre de campo incorrecto | usar `refresh` | | la URL de pago no abre | bug cliente | se está usando `pk` en vez del slug `url` | construir `{baseUrl}/{url}` | Categorías internas sugeridas [#categorías-internas-sugeridas] | Categoría | Úsala para | | --------------------------- | ------------------------------------------------------------------- | | `configuration_error` | credenciales faltantes, ambiente incorrecto, callback URL ausente | | `request_validation_error` | payloads mal formados, tipos inválidos, campos requeridos ausentes | | `authentication_error` | material de auth inválido o expirado | | `provider_processing_error` | Cobru o un proveedor downstream falló después de validar el request | | `reconciliation_error` | el callback y el estado del pago no coinciden con tu estado interno | Checklist de troubleshooting [#checklist-de-troubleshooting] 1. Confirma que estás usando la base URL correcta. 2. Confirma que las tres credenciales están presentes. 3. Loguea el JSON exacto antes de enviarlo. 4. Verifica que `payment_method_enabled` vaya serializado como string. 5. Confirma que `callback` y `payer_redirect_url` sean URLs HTTPS válidas. 6. Conserva las respuestas raw de Cobru en logs durante la integración. Qué conviene loguear en cada request fallido [#qué-conviene-loguear-en-cada-request-fallido] * request ID interno * endpoint y método Cobru * body sanitizado enviado * status HTTP * respuesta raw de Cobru * categoría interna del error * decisión de retry Guía de reintentos [#guía-de-reintentos] Solo reintenta cuando el fallo parezca transitorio y la operación sea segura de repetir. En creación de pagos, mantén comportamiento idempotente del lado interno aunque Cobru no exponga idempotencia formal en todos los endpoints. No hagas retry automático para payloads mal formados, callback URLs faltantes, serialización incorrecta de `payment_method_enabled` o nombres erróneos de campos de auth. Son errores de request, no de disponibilidad. Modelo deseable a futuro [#modelo-deseable-a-futuro] Un modelo futuro de errores en Cobru debería migrar a `application/problem+json` con tipos de error estables y legibles por máquina. Hasta entonces, conviene normalizar las respuestas de Cobru a tu propio formato interno. --- # Inicio rápido Locale: es URL: https://docs.cobru.co/es/docs/getting-started Prerrequisitos [#prerrequisitos] * Cuenta Cobru con credenciales desde [panel.cobru.co](https://panel.cobru.co) * Dos credenciales del dashboard: `x-api-key`, `refresh_token` * URL base sandbox: `https://dev.cobru.co` Esta página cubre solo el camino más corto a una integración funcional. Para el modelo completo de autenticación, caché del token y seguridad, sigue con `/docs/authentication`. Paso 1. Obtener un access token [#paso-1-obtener-un-access-token] ```bash curl -X POST https://dev.cobru.co/token/refresh/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Content-Type: application/json" \ -d '{"refresh":"'"$COBRU_REFRESH_TOKEN"'"}' ``` El campo es `refresh`, **no** `refresh_token`. La documentación del plugin WooCommerce es incorrecta en este punto. **Respuesta `200`:** ```json { "access": "eyJ0eXAi..." } ``` El token `access` tiene un TTL de \~60 minutos. Guárdalo en caché máximo 50 minutos. Paso 2. Crear un pago [#paso-2-crear-un-pago] ```bash curl -X POST https://dev.cobru.co/cobru/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Authorization: Bearer $COBRU_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "amount": 50000, "description": "Orden #123", "expiration_days": 1, "client_assume_costs": false, "iva": 0, "payment_method_enabled": "{\"breb\":true,\"bancolombia_qr\":true,\"pse\":true}", "payer_redirect_url": "https://tuapp.com/pago-exitoso", "callback": "https://tuapp.com/api/cobru/webhook" }' ``` `payment_method_enabled` debe ser un **string JSON serializado** — ejecuta `JSON.stringify({...})` antes de incluirlo. Enviarlo como objeto plano devuelve HTTP 400. Incluye siempre `payer_redirect_url` y `callback`. Si falta alguno, Cobru puede responder con HTTP `403` aunque el problema real sea validación del request. **Respuesta `201`:** ```json { "pk": 27150, "url": "3gofdf6f", "amount": "50000.00", "state": 0, "fee_amount": 2395, "currency_code": "COP", "idempotency_key": "3114242222_8de7c88b84..." } ``` Paso 3. Compartir la URL de pago [#paso-3-compartir-la-url-de-pago] ```typescript // CORRECTO const paymentUrl = `${COBRU_BASE_URL}/${response.url}`; // Ejemplo: https://dev.cobru.co/3gofdf6f // INCORRECTO (patrón del plugin WooCommerce — NO funciona) const paymentUrl = `${COBRU_BASE_URL}/pay/${response.pk}`; ``` Desde aquí puedes: * enviar el link directamente por email, SMS o chat * convertirlo en un PNG QR usando `api.qrserver.com` * usar el flujo BRE-B + QR documentado en `/docs/guides/qr-breb` Paso 4. Recibir el webhook [#paso-4-recibir-el-webhook] ```ts export async function POST(request: Request) { const payload = await request.json(); // Primero persistir, luego procesar. console.log('Cobru webhook:', payload); return new Response('ok', { status: 200 }); } ``` Los webhooks de Cobru no están firmados hoy. Trata el callback como un trigger, no como fuente única de verdad para operaciones de alto riesgo. Variables de entorno [#variables-de-entorno] ```bash COBRU_BASE_URL=https://dev.cobru.co # sandbox COBRU_API_KEY=tu_api_key COBRU_REFRESH_TOKEN=tu_refresh_token NEXT_PUBLIC_APP_URL=https://tuapp.com ``` Siguientes pasos [#siguientes-pasos] 1. Lee `/docs/authentication` para el caché del token y límites de seguridad. 2. Lee `/docs/webhooks` para idempotencia y patrones de validación. 3. Lee `/docs/api/cobrus/create` para el contrato completo de creación de pagos. --- # Payments Locale: es URL: https://docs.cobru.co/es/docs Cobru es una plataforma de pagos colombiana para equipos que necesitan lanzar links de pago hosted, soportar métodos locales, automatizar cobranzas y operar movimiento de dinero desde una sola API. Esta documentación está organizada para llevarte por el camino más corto hacia una salida a producción segura. Cada ruta crítica está pensada para humanos leyendo linealmente y para agentes de IA consumiendo páginas, markdown y salidas `llms.txt`. Elige un camino [#elige-un-camino] Qué leer primero [#qué-leer-primero] 1. [Inicio rápido](/es/docs/getting-started) para crear el primer payment link. 2. [Autenticación](/es/docs/authentication) para endurecer el manejo de tokens. 3. [Webhooks](/es/docs/webhooks) para modelar estado asíncrono de forma segura. 4. [Platform](/es/docs/platform) para validar testing, troubleshooting y workflows asistidos con IA. 5. [Referencia API](/es/docs/api/reference) cuando necesites request y response shapes exactos. Superficie de producto [#superficie-de-producto] | Área | Para qué la usa un developer | | ---------------- | ---------------------------------------------------------------------------------------------------------------------- | | Payments | Crear Cobrus hosted, calcular fees, inspeccionar detalles de pago y manejar métodos locales | | Payouts | Mover saldo, ejecutar retiros en efectivo, retiros bancarios y flujos de settlement BRE-B | | Platform | Autenticar de forma segura, consumir webhooks, probar antes del go-live, diagnosticar incidentes y navegar el contrato | | Cards & Services | Operar tarjetas, tokenización, recargas, PINes y otras APIs visibles del producto | Ambientes [#ambientes] | Ambiente | URL base | | ---------- | ----------------------- | | Sandbox | `https://dev.cobru.co` | | Producción | `https://prod.cobru.co` | Modelo documental AI-first [#modelo-documental-ai-first] * Cada página narrativa expone una salida markdown reusable. * `llms.txt` y `llms-full.txt` se mantienen públicos y crawlables. * La guía específica para IA vive en [Build with AI](/es/docs/build-with-ai). * Las páginas con verificación incompleta siguen etiquetadas explícitamente en vez de maquillarse como certeza. Verificación y soporte [#verificación-y-soporte] | Fuente | Rol | | ---------------------------------- | -------------------------------------------------------------------------- | | sandbox `dev.cobru.co` | Fuente principal para verificar comportamiento real | | materiales API históricos de Cobru | Fuente secundaria para endpoints aún no revalidados | | capturas del menú API de Cobru | Fuente de alcance para familias pendientes de extracción de contrato | | `soporte@cobru.co` | Ruta de escalación cuando un contrato debe confirmarse antes de producción | --- # Preparación para producción Locale: es URL: https://docs.cobru.co/es/docs/production-readiness Salir a producción con Cobru no es solo cambiar credenciales. Trata la preparación para producción como un hito operativo con checks explícitos sobre auth, creación de pagos, callbacks, observabilidad y soporte. Empieza aquí [#empieza-aquí] 1. Confirma credenciales de producción, callback URL y estrategia de logging. 2. Ensaya un pago end to end con conciliación manual. 3. Verifica que soporte pueda rastrear un pago desde tu order ID interno hasta los objetos Cobru. 4. Define criterios de rollback antes de abrir tráfico amplio. Checklist de go-live [#checklist-de-go-live] Confirma que las credenciales de producción se guardan solo en configuración segura del servidor y no se comparten con frontend. Cambia la base URL a `https://prod.cobru.co` solo después de pasar flujos consistentes en sandbox. Confirma que tu `callback` URL es pública, HTTPS, monitoreada e idempotente. Valida que el equipo puede reconciliar manualmente un pago desde request hasta callback y estado interno. Asegura que soporte puede ubicar pagos por order ID interno y por slug `url` de Cobru. Controles mínimos antes de tráfico real [#controles-mínimos-antes-de-tráfico-real] | Área | Requisito | | ---------- | ------------------------------------------------------------------------ | | Auth | caché de access token y almacenamiento seguro de secretos | | Payments | serialización segura de `payment_method_enabled` y redirects confiables | | Webhooks | respuesta `200` rápida, persistencia, deduplicación y reconciliación | | Logging | request IDs, responses raw de Cobru y logs de eventos webhook | | Support | capacidad de trazar un pago desde la orden interna hasta el objeto Cobru | | Monitoring | alertas sobre fallas al crear pagos y al procesar webhooks | Estrategia recomendada de lanzamiento [#estrategia-recomendada-de-lanzamiento] * empieza con tráfico interno o de bajo riesgo * mantén conciliación manual durante los primeros días * evita comunicación amplia a clientes hasta confirmar estabilidad de callbacks * documenta ownership de incident response para la semana de lanzamiento Áreas sensibles en producción [#áreas-sensibles-en-producción] Algunas requests malformadas de creación de pago todavía pueden aparecer como `403` en vez de un status limpio de validación. Tu monitoreo debe preservar las responses raw de Cobru. Como los callbacks de Cobru no están firmados hoy, tu sistema de producción debe tratarlos como notificaciones y volver a validar estado antes de acciones irreversibles. Construye siempre la URL hosted a partir del slug `url` devuelto por Cobru, no desde `pk` ni desde patrones antiguos de plugins. Criterios de rollback del día de salida [#criterios-de-rollback-del-día-de-salida] Pausa o limita tráfico real si: * cae inesperadamente el success rate de creación de pagos * dejan de llegar callbacks o no puedes reconciliarlos * no puedes empatar pagos Cobru con órdenes internas de forma confiable * soporte no puede diagnosticar fallas con la información disponible Sigue con [#sigue-con] * `/docs/testing` * `/docs/webhooks` * `/docs/errors` * `/docs/troubleshooting` --- # Pruebas Locale: es URL: https://docs.cobru.co/es/docs/testing Empieza aquí [#empieza-aquí] 1. Emite un access token en sandbox. 2. Crea un pago real desde tu backend. 3. Abre la URL hosted construida desde el `url` slug devuelto. 4. Confirma redirects y callback handling en tu propio sistema. 5. Registra suficiente evidencia para poder depurar la corrida después. Ambiente sandbox [#ambiente-sandbox] | Propiedad | Valor | | --------------- | -------------------------------------------------------------------------------------------- | | Base URL | `https://dev.cobru.co` | | Propósito | desarrollo, QA, depuración de integración | | Credenciales | separadas de producción | | Fees | no representan economía real de producción | | Uso recomendado | validación de auth, creación de pagos, checkout hosted, manejo de webhooks, pruebas QR/BRE-B | Trata sandbox como un ambiente de validación de comportamiento, no como fuente de verdad para economía de producción, tiempos de settlement o procedimientos de soporte. Flujo de prueba recomendado [#flujo-de-prueba-recomendado] 1. Emite un access token. 2. Crea un pago en sandbox. 3. Construye la URL hosted usando el `url` slug devuelto. 4. Completa el flujo manualmente en la página de Cobru. 5. Confirma que tu webhook recibe el cambio de estado esperado. Matriz mínima de pruebas [#matriz-mínima-de-pruebas] | Escenario | Qué verificar | | ----------------------- | ------------------------------------------------------------------------- | | refresh del token | `POST /token/refresh/` funciona con tu estrategia de credenciales y caché | | creación de pago | tu backend envía `payment_method_enabled` como string JSON y recibe `201` | | URL hosted | tu app usa `response.url`, no `response.pk`, para construir el checkout | | redirects | `payer_redirect_url` resuelve correctamente después del pago | | callback handling | tu endpoint persiste, deduplica y responde rápido a callbacks | | consulta/reconciliación | tu sistema puede reconciliar el pago después de callback o soporte manual | Fixtures y cuentas recomendadas [#fixtures-y-cuentas-recomendadas] * una orden de bajo valor para smoke tests * una orden con BRE-B habilitado * una orden con múltiples métodos de pago habilitados * un fixture de payload inválido para confirmar normalización de errores * un fixture de replay de webhook para verificar idempotencia Pruebas locales de webhooks [#pruebas-locales-de-webhooks] ```bash ngrok http 3000 ``` Usa la URL HTTPS generada como tu campo `callback` en la request de creación de pago. Qué registrar en cada corrida [#qué-registrar-en-cada-corrida] * request body enviado a Cobru * response body raw de Cobru * URL de pago generada * todos los payloads webhook * tu propio resultado de conciliación * el order ID interno o referencia de pago que mapeaste con Cobru Errores comunes de sandbox [#errores-comunes-de-sandbox] Confirma que construyes la URL hosted como `{COBRU_BASE_URL}/{url}`. Los patrones antiguos con `/pay/{pk}` ya no reflejan el comportamiento actual. Revisa primero validación del body. Falta de `callback`, falta de `payer_redirect_url` o enviar `payment_method_enabled` como objeto pueden aparecer como `403` engañosos. Es lo esperado. Trata los callbacks como notificaciones y vuelve a verificar detalle de pago o estado interno antes de liberar valor de alto riesgo. Criterios de salida antes de producción [#criterios-de-salida-antes-de-producción] * puedes crear y completar un pago end to end desde tu app * puedes persistir y deduplicar callbacks * puedes reconciliar manualmente un pago con datos Cobru y tu propio estado de orden * tus logs incluyen suficiente información para depurar un pago fallido sin adivinar * tus credenciales no están hardcodeadas fuera del almacenamiento seguro del servidor Sigue con [#sigue-con] * `/docs/production-readiness` * `/docs/webhooks` * `/docs/troubleshooting` * `/docs/errors` --- # Resolución de problemas Locale: es URL: https://docs.cobru.co/es/docs/troubleshooting Usa esta página cuando la integración esté fallando y necesites una ruta concreta de diagnóstico, no solo guía general de API. Orden de triage rápido [#orden-de-triage-rápido] 1. Confirma ambiente y base URL. 2. Confirma que las credenciales requeridas estén presentes. 3. Inspecciona el JSON exacto enviado a Cobru. 4. Inspecciona la respuesta raw de Cobru. 5. Verifica si la URL hosted se construyó desde `url`. 6. Verifica si los callbacks están llegando y deduplicándose. Mapa de fallos comunes [#mapa-de-fallos-comunes] | Síntoma | Primera cosa que debes revisar | | -------------------------------------- | ---------------------------------------------------------------- | | `403` al crear pago | validación del request, no solo auth | | `400` al crear pago | serialización de `payment_method_enabled` | | la página de pago no abre | la URL hosted se construyó con `pk` en lugar de `url` | | llega callback pero la orden no cambia | persistencia del webhook y procesamiento asíncrono | | acciones de negocio duplicadas | falta de idempotencia en el handler del webhook | | flujo de payouts poco claro | valida el nivel de confianza del endpoint antes de implementarlo | Triage de creación de pago [#triage-de-creación-de-pago] Revisa `callback`, `payer_redirect_url`, content type y la forma de `payment_method_enabled`. Cobru puede surfacer fallas de validación como `403`. Envía `payment_method_enabled` como string JSON, no como objeto anidado. Construye la URL como `{COBRU_BASE_URL}/{response.url}`. No uses `/pay/{pk}`. Triage de webhooks [#triage-de-webhooks] Añade deduplicación usando `orderId`, `url` o tu propia referencia interna. Trata entregas duplicadas como normales hasta que Cobru documente garantías más fuertes. Reconcília el pago antes de despachar bienes o marcar éxito irreversible. Lo que soporte siempre debe tener a mano [#lo-que-soporte-siempre-debe-tener-a-mano] * order ID interno * slug `url` de Cobru * timestamp de creación del pago * body raw del error Cobru cuando falle la creación * payload raw del webhook cuando exista callback Cuándo escalar a Cobru [#cuándo-escalar-a-cobru] * cuando sandbox y producción difieran de forma no documentada * cuando un endpoint documentado como legacy se comporte distinto a la documentación publicada * cuando veas fallas sostenidas de proveedor sin detalles de error accionables Páginas relacionadas [#páginas-relacionadas] * `/docs/testing` * `/docs/webhooks` * `/docs/errors` * `/docs/api/reference` --- # Webhooks Locale: es URL: https://docs.cobru.co/es/docs/webhooks Cobru envía un `POST` a la URL `callback` que incluyes al crear un pago. Hoy esta es la vía principal para reaccionar a actualizaciones de pago desde tu propio backend. Empieza aquí [#empieza-aquí] 1. Trata el callback como notificación, no como fuente de verdad. 2. Persiste el evento raw inmediatamente. 3. Responde HTTP `200` rápido. 4. Deduplica por identificadores Cobru o por tu propia referencia de pago. 5. Reconcilia antes de liberar valor irreversible. Modelo de confianza actual [#modelo-de-confianza-actual] Los webhooks de Cobru no están firmados hoy. No existe un contrato público de HMAC header o verificación JWT. Trata el webhook como notificación, no como prueba definitiva. Payload típico [#payload-típico] ```json { "orderId": "123", "state": 3, "payment_method": "Bre-B", "amount": "50000.00", "url": "3gofdf6f" } ``` Estados de pago [#estados-de-pago] | Estado | Significado | Notas | | ------ | --------------------- | ----------------------------------------------------------------------------- | | `0` | Creado / pendiente | el objeto de pago existe | | `1` | Procesando | el usuario inició o Cobru espera confirmación final | | `2` | No pagado / rechazado | el resultado depende del método | | `3` | Pagado / aprobado | el estado que la mayoría de equipos trata como settlement exitoso | | `4` | Reembolsado | reembolso aplicado | | `5` | Expirado | aparece en materiales históricos de Cobru; confírmalo antes de depender de él | Qué debe hacer una integración segura de webhooks [#qué-debe-hacer-una-integración-segura-de-webhooks] Recibir el callback, parsear el JSON y persistir el payload raw de inmediato. Responder HTTP `200` rápido para que Cobru no dependa del tiempo de tu procesamiento downstream. Deduplicar por `orderId`, `url` o tu propia referencia interna del pago. Reconciliar el pago antes de despachar bienes, liberar valor o marcar éxito irreversible. Patrón recomendado para el handler [#patrón-recomendado-para-el-handler] 1. Parsea el payload. 2. Persiste el evento inmediatamente. 3. Responde HTTP `200` lo más rápido posible. 4. Procesa reconciliación y side effects de forma asincrónica. 5. Protege acciones downstream con idempotencia usando `orderId` o tu propia referencia. ```ts export async function POST(request: Request) { const payload = await request.json(); await saveWebhookEvent(payload); return new Response('ok', { status: 200 }); } ``` Modelo de persistencia recomendado [#modelo-de-persistencia-recomendado] Guarda al menos: * payload raw * timestamp de recepción * order ID interno * slug `url` de Cobru * `orderId` de Cobru cuando exista * resultado del procesamiento * contador de replay o marca de deduplicación Opciones de hardening disponibles hoy [#opciones-de-hardening-disponibles-hoy] | Riesgo | Workaround actual | | ------------------------------------ | --------------------------------------------------------------------- | | cualquiera puede golpear tu callback | incluye tu propio secreto en el query string del callback | | entregas duplicadas | guarda `orderId` y salta eventos ya procesados | | spoofing del callback | vuelve a consultar detalles del pago con Cobru antes de liberar valor | | puntos ciegos operativos | loguea todos los callbacks y expón una herramienta interna de replay | Qué no debes hacer [#qué-no-debes-hacer] * no marques una orden como definitivamente exitosa antes de reconciliar * no ejecutes trabajo pesado downstream antes de responder `200` * no confíes solo en la IP de origen como control de seguridad * no asumas que los callbacks llegan exactamente una sola vez Pruebas locales [#pruebas-locales] ```bash ngrok http 3000 ``` Luego usa esa URL pública HTTPS como tu valor `callback` en sandbox. Controles recomendados para producción [#controles-recomendados-para-producción] | Control | Por qué importa | | ----------------------------------------- | --------------------------------------------------------------- | | secreto en callback o token no adivinable | reduce riesgo de spoofing trivial | | event log persistente | permite depurar incidentes y replays | | procesador idempotente | protege contra duplicados | | paso de reconciliación | evita falsos positivos cuando el callback es incompleto o falso | | alertas sobre fallas de procesamiento | reduce errores silenciosos en pagos | Sigue con [#sigue-con] * `/docs/testing` * `/docs/production-readiness` * `/docs/troubleshooting` * `/docs/api/cobrus/create` --- # Balances Locale: es URL: https://docs.cobru.co/es/docs/guides/balances El endpoint de balance viene de materiales legacy de Cobru. La ruta es útil, pero el contrato completo todavía necesita una validación fresca en sandbox. Endpoint [#endpoint] `GET /balance/` Usos típicos [#usos-típicos] * validaciones previas antes de envíos o retiros * sincronización de saldo en dashboard * vistas de tesorería y conciliación Respuesta observada en documentación legacy [#respuesta-observada-en-documentación-legacy] ```json { "balance": "14179.25", "balance_cop": "14179.25", "balance_usd": "9995.00", "balance_ars": "10000.00", "balance_mxn": "96536.31", "balance_brl": "89772737.20" } ``` Ejemplo de request [#ejemplo-de-request] ```bash curl -X GET https://dev.cobru.co/balance/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Authorization: Bearer $COBRU_ACCESS_TOKEN" ``` ```ts const response = await fetch('https://dev.cobru.co/balance/', { method: 'GET', headers: { 'x-api-key': process.env.COBRU_API_KEY!, Authorization: `Bearer ${accessToken}`, }, }); const balance = await response.json(); console.log(balance.balance_cop); ``` ```python import requests response = requests.get( "https://dev.cobru.co/balance/", headers={ "x-api-key": COBRU_API_KEY, "Authorization": f"Bearer {access_token}", }, ) print(response.json()) ``` ```php request('GET', 'https://dev.cobru.co/balance/', [ 'headers' => [ 'x-api-key' => getenv('COBRU_API_KEY'), 'Authorization' => 'Bearer ' . $accessToken, ], ]); $balance = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR); var_dump($balance); ``` Guía de integración [#guía-de-integración] Usa la lectura de balance como snapshot operativo, no como única fuente de verdad para settlement. Combínala con movimientos y estados de pagos o retiros. Para dashboards es razonable cachear por poco tiempo. Para payouts o retiros, vuelve a consultar el saldo inmediatamente antes de ejecutar la operación. La respuesta legacy incluye saldos en COP, USD, ARS, MXN y BRL. Confirma cuáles son realmente significativos para tu tipo de cuenta antes de mostrarlos en UI de producción. --- # Movimientos Locale: es URL: https://docs.cobru.co/es/docs/guides/movements El contrato de movimientos de Cobru sigue viniendo de materiales legacy. La forma de la ruta es prometedora, pero parámetros y respuesta necesitan una nueva validación antes de usarlos para contabilidad automatizada. Por qué importa esta guía [#por-qué-importa-esta-guía] El historial de movimientos es una necesidad operativa recurrente en pagos, envíos, retiros y tarjetas. Patrón de endpoint [#patrón-de-endpoint] `GET /movements/movements_by_types/?{type_req}=true&per_page={number}&page_num={number}` Valores `type_req` descritos en Spotlight: * `by_cobrus` * `by_withdraws` * `by_sends` * `by_other_payments` Debes enviar un solo filtro por request. Ejemplo de request [#ejemplo-de-request] ```bash curl -G https://dev.cobru.co/movements/movements_by_types/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Authorization: Bearer $COBRU_ACCESS_TOKEN" \ --data-urlencode "by_cobrus=true" \ --data-urlencode "per_page=10" \ --data-urlencode "page_num=1" ``` ```ts const url = new URL('https://dev.cobru.co/movements/movements_by_types/'); url.searchParams.set('by_cobrus', 'true'); url.searchParams.set('per_page', '10'); url.searchParams.set('page_num', '1'); const response = await fetch(url, { headers: { 'x-api-key': process.env.COBRU_API_KEY!, Authorization: `Bearer ${accessToken}`, }, }); const movements = await response.json(); console.log(movements); ``` ```python import requests response = requests.get( "https://dev.cobru.co/movements/movements_by_types/", headers={ "x-api-key": COBRU_API_KEY, "Authorization": f"Bearer {access_token}", }, params={ "by_cobrus": "true", "per_page": 10, "page_num": 1, }, ) print(response.json()) ``` ```php request('GET', 'https://dev.cobru.co/movements/movements_by_types/', [ 'headers' => [ 'x-api-key' => getenv('COBRU_API_KEY'), 'Authorization' => 'Bearer ' . $accessToken, ], 'query' => [ 'by_cobrus' => 'true', 'per_page' => 10, 'page_num' => 1, ], ]); $movements = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR); var_dump($movements); ``` Checklist de conciliación [#checklist-de-conciliación] Persiste primero los payloads de webhook de Cobru y procésalos de forma asíncrona. Conciliá una fila de movimiento con identificadores de pago o retiro, no solo por monto. Recorre histórico cuando un webhook falle, llegue tarde o deje un estado ambiguo. Advertencias de integración [#advertencias-de-integración] Spotlight dice explícitamente que no se deben enviar todos los type flags al mismo tiempo. Diseña tus jobs de sincronización para consultar una familia de movimientos por request. El ejemplo de respuesta incluye campos presentacionales como `img` y campos de payer o impuestos. Trátalos como informativos hasta revalidar el contrato actual. Prefiere `pk`, `reference_cobru`, `url` e IDs específicos de la operación por encima de campos derivados o de display para unir movimientos con tus registros internos. --- # Flujo de pago Bre-B Locale: es URL: https://docs.cobru.co/es/docs/guides/qr-breb Qué cubre esta guía [#qué-cubre-esta-guía] Esta guía reemplaza la narrativa anterior centrada solo en QR y documenta el flujo Bre-B tal como aparece en los materiales originales de Spotlight de Cobru. El flujo tiene dos partes: 1. Crear un cobru con Bre-B habilitado en `payment_method_enabled` 2. Enviar detalles de pago a `POST /{url}` con `payment: "breb"` En narrativa pública usamos Bre-B, pero los payloads conservan el literal exacto del backend tal como aparece en el contrato del request: `payment: "breb"` y `"breb": true` dentro de `payment_method_enabled`. Modos de salida de Bre-B [#modos-de-salida-de-bre-b] Hay dos formas muy distintas de ofrecer una experiencia Bre-B con Cobru: | Modo | Qué generas | Requiere página hosted de Cobru | Qué escanea el pagador | | ----------------- | --------------------------------------------------------------------------------- | ------------------------------- | ------------------------------------------------ | | QR de link hosted | un QR que apunta a `https://dev.cobru.co/{slug}` o `https://prod.cobru.co/{slug}` | sí | una URL que abre la página de Cobru | | QR Bre-B nativo | un QR generado a partir del string de payload Bre-B que retorna Cobru | no | un string EMV/Bre-B procesado por apps bancarias | Si tu objetivo es específicamente generar un **QR Bre-B sin el link de pago**, necesitas la segunda ruta: obtener el string de payload Bre-B desde Cobru y renderizar tú mismo el QR. Paso 1 — Crear el cobru [#paso-1--crear-el-cobru] ```json { "amount": 20000, "description": "Cobro Bre-B", "expiration_days": 1, "client_assume_costs": false, "iva": 0, "payment_method_enabled": "{\"breb\":true}", "payer_redirect_url": "https://tuapp.com/pago/exitoso", "callback": "https://tuapp.com/api/cobru/webhook" } ``` Spotlight y los learnings posteriores coinciden en un quirk crítico: `payment_method_enabled` debe ser un string JSON, no un objeto anidado. Paso 1.5 — Habilitar la capacidad correcta de Bre-B [#paso-15--habilitar-la-capacidad-correcta-de-bre-b] El paso de creación debe habilitar Bre-B con `"breb": true` dentro de `payment_method_enabled`. El research profundo posterior también encontró un segundo literal de checkout, `breb_qr`, usado por los internos del checkout hosted de Cobru. Para fines de documentación, trátalos así: | Capacidad | De dónde sale | Qué significa | | ------------------------------------------ | ------------------- | ------------------------------------------------------------------------ | | `"breb": true` en `payment_method_enabled` | payload del request | el cobru debe ofrecer Bre-B | | `payment: "breb"` | Spotlight | request directo de detalles de pago Bre-B | | `payment: "breb_qr"` | research profundo | variante Bre-B enfocada en QR vista en análisis posteriores del checkout | El research posterior en sandbox observó `payment: "breb"` directo como restringido comercialmente o deshabilitado en algunos entornos. Ten en cuenta ambas variantes si vas a implementar un flujo de QR Bre-B nativo. Paso 2 — Enviar los detalles de pago Bre-B [#paso-2--enviar-los-detalles-de-pago-bre-b] Llama el slug del cobru retornado por `POST /cobru/`: `POST /{url}` ```json { "payment": "breb" } ``` Los materiales originales de Spotlight describen Bre-B como un método de transferencia rápida ligado a la app Bre-B o a la llave (`llaves`) del usuario. Generar un QR Bre-B nativo sin el link de pago [#generar-un-qr-bre-b-nativo-sin-el-link-de-pago] Esta es la sección que la mayoría de equipos realmente necesita. Si **no** quieres mandar al pagador a la página hosted de Cobru, el flujo es: 1. crear el cobru con Bre-B habilitado 2. llamar `POST /{url}` para la variante Bre-B de checkout 3. extraer el string de payload Bre-B que retorna Cobru 4. generar la imagen QR en tu frontend o backend 5. mostrar el QR junto con la llave Bre-B al pagador ¿Qué campo debes usar para armar el QR? [#qué-campo-debes-usar-para-armar-el-qr] Los materiales fuente son inconsistentes, así que tu integración debe normalizar todos los nombres de campo conocidos: | Fuente | Nombre del campo | Significado | | --------------------------------- | ---------------------------- | ------------------------------------------------------------------ | | Spotlight | `check_qr` | string que se usa para armar el QR | | Ejemplo de respuesta en Spotlight | `qr_value` | payload QR expuesto dentro de `api.paymentorder` | | research profundo posterior | `payment_details.qr_bitcoin` | string EMV encontrado en los internos del checkout hosted de Cobru | | Spotlight y research posterior | `key_value` | llave Bre-B mostrada al usuario | Regla práctica: * primero busca `check_qr` * luego usa `qr_value` como fallback * si integras contra la ruta posterior del checkout hosted, revisa también `payment_details.qr_bitcoin` Ejemplo de normalización [#ejemplo-de-normalización] ```ts const qrPayload = response?.check_qr ?? response?.qr_value ?? response?.payment_details?.qr_bitcoin ?? response?.fields?.check_qr ?? response?.fields?.qr_value; const keyValue = response?.key_value ?? response?.payment_details?.key_value ?? response?.fields?.key_value; if (!qrPayload) { throw new Error('Cobru no retornó un payload QR Bre-B'); } ``` Ejemplo de generación del QR [#ejemplo-de-generación-del-qr] ```ts import QRCode from 'qrcode'; const qrDataUrl = await QRCode.toDataURL(qrPayload, { errorCorrectionLevel: 'M', margin: 1, width: 320, }); ``` Usa la imagen generada dentro de tu propio checkout. Si tu objetivo es un QR Bre-B nativo, no codifiques la URL hosted de Cobru. Campos que deberías mostrar en tu UI [#campos-que-deberías-mostrar-en-tu-ui] | Campo | ¿Mostrarlo al pagador? | Por qué | | -------------------------------------- | ---------------------- | ---------------------------------------------------------------------- | | `qr_value` / `check_qr` / `qr_bitcoin` | sí | es el payload que conviertes en QR | | `key_value` | sí | sirve como fallback cuando el pagador quiere copiar o digitar la llave | | `amount` | sí | ayuda a validar el cobro | | `state` | interno y UI | la transacción inicia como pendiente | | `GOrdenId` | interno | útil para correlación y consultas posteriores | Tiempo de vida [#tiempo-de-vida] Spotlight dice que `qr_value` y `key_value` viven **5 minutos**. El reverse engineering posterior también observó `time_to_complete: 520` segundos en la lógica de la página de Cobru, o sea aproximadamente **8.6 minutos**. La regla operativa correcta es: * tu UX debe asumir una instrucción Bre-B de vida **muy corta** * debes regenerar o refrescar el QR cuando expire la ventana * nunca reutilices un payload Bre-B viejo para una nueva transacción Limitación actual [#limitación-actual] El research profundo posterior encontró que Cobru **no** expone un QR Bre-B estático simple que cualquier pagador pueda escanear indefinidamente. El QR Bre-B nativo está ligado a la transacción y, en pruebas posteriores de sandbox, puede requerir datos reales del pagador o habilitación comercial. Eso significa: * sí puedes generar un QR Bre-B sin usar el link hosted * pero primero dependes de que Cobru te devuelva un payload Bre-B específico de la transacción * esto no equivale a tener un QR estático reutilizable de comercio Ruta alternativa de QR nativo observada en research posterior [#ruta-alternativa-de-qr-nativo-observada-en-research-posterior] El research posterior del checkout también encontró una variante enfocada en QR: ```json { "payment": "breb_qr" } ``` Caveats importantes de ese research: * fue observada en una implementación posterior del checkout de Cobru, no en el contrato Spotlight original * las pruebas en sandbox sugirieron que puede requerir documento real del pagador * la respuesta parece más cercana a `payment_details.qr_bitcoin` que al wording `check_qr` de Spotlight Úsala solo si: * `breb` directo no está disponible en tu entorno * soporte de Cobru confirma `breb_qr` para tu cuenta * estás listo para probar con datos de pagador compatibles con sandbox Forma de respuesta esperada [#forma-de-respuesta-esperada] Spotlight muestra una respuesta que contiene tanto un objeto `api.paymentorder` como un objeto `api.cobru`. Los campos Bre-B más importantes son: | Campo | Significado | | ----------- | --------------------------------------------- | | `method` | `breb` | | `franchise` | `breb` | | `qr_value` | payload QR expuesto por Cobru en la respuesta | | `key_value` | llave Bre-B mostrada al usuario | | `GOrdenId` | identificador de orden del gateway | Fragmento de ejemplo de los materiales originales: ```json [ { "model": "api.paymentorder", "fields": { "method": "breb", "franchise": "breb", "state": "PENDIENTE", "amount": "20000.00", "qr_value": "9893839849384938434.COM.CRB.LLA04...", "key_value": "@llave0343" } }, { "model": "api.cobru", "fields": { "url": "urmndopt" } } ] ``` Ventana de expiración [#ventana-de-expiración] Los materiales de Spotlight indican explícitamente que tanto `qr_value` como `key_value` viven **5 minutos**. Trátalos como instrucciones de pago de corta duración, no como identificadores reutilizables. Cómo se relaciona esto con la addenda de QR [#cómo-se-relaciona-esto-con-la-addenda-de-qr] El contrato Spotlight de arriba es la fuente principal del flujo de pago Bre-B. Además existe un patrón posterior verificado: * crear un cobru con Bre-B habilitado * construir la URL hosted de Cobru usando el slug retornado * generar un PNG QR externo que apunte a la página de pago hosted * enviarlo por canales como WhatsApp Ese patrón QR es útil cuando tu producto necesita distribuir una imagen escaneable, pero es una addenda sobre el flujo Bre-B original, no el contrato base. Addenda verificada: Cobru no expone un endpoint PNG de QR. Si tu UX necesita una imagen QR compartible, debes generarla desde la URL hosted del cobru. Árbol de decisión recomendado [#árbol-de-decisión-recomendado] | Si necesitas... | Ruta recomendada | | ----------------------------------------- | ---------------------------------------------------------------------------------- | | el MVP más simple | usa el link hosted de Cobru y genera un QR que apunte a la página de pago | | un QR Bre-B nativo dentro de tu propia UI | llama el flujo Bre-B de detalles de pago y renderiza tú mismo el payload retornado | | un QR bancario estático reutilizable | no asumas que Cobru lo expone hoy; pregunta a Cobru o usa un proveedor alternativo | Cuándo usar Bre-B [#cuándo-usar-bre-b] Usa Bre-B cuando: * el pagador puede completar una transferencia interoperable bancaria * tu checkout debe mostrar Bre-B como opción principal * puedes trabajar con instrucciones de pago de vida corta y confirmación por webhook Si necesitas un flujo hosted con selección explícita de banco, PSE encaja mejor. Páginas relacionadas [#páginas-relacionadas] * [Crear un cobru](/es/docs/api/cobrus/create) * [Enviar detalles de pago](/es/docs/api/cobrus/payment-details) * [Códigos de bancos PSE](/es/docs/api/cobrus/pse-banks) * [Pagos PSE](/es/docs/api/cobrus/pse) --- # Marca blanca Locale: es URL: https://docs.cobru.co/es/docs/guides/whitelabel Cobru puede sentirse integrado en tu producto incluso cuando el checkout o ciertas superficies siguen siendo hosted, si diseñas bien la transición. El material original de Spotlight también documenta una superficie de registro de usuarios white-label importante para productos financieros embebidos. El onboarding white-label y los usernames prefijados por marca vienen de documentación legacy de Cobru. No lo publiques como contrato definitivo sin confirmarlo con tu equipo de Cobru. Qué cubre esta capability [#qué-cubre-esta-capability] * registrar usuarios bajo un namespace o marca aliada * consultar categorías y subcategorías antes del registro * confirmar correo y teléfono * integrar flujos Cobru dentro de la experiencia de tu propio producto Flujo de registro [#flujo-de-registro] Consulta categorías con `GET /category/` y subcategorías con `GET /subcategory?category_id=...`. Recolecta el payload de registro con `brand`, `username`, `documents` y campos legales. Crea el usuario con `POST /user/`. Completa flujos posteriores como confirmación de correo y teléfono. Payload de ejemplo [#payload-de-ejemplo] ```json { "username": "09906786442", "first_name": "Test", "last_name": "User", "email": "test@example.com", "password": "12345678", "phone": "09906786442", "document_type": "0", "document_number": "11111122223", "country_code": "+57", "gender": 2, "date_birth": "2001-08-08", "type_person": 1, "date_expiration": "2019-08-08", "subcategory": 745, "category": 99, "platform": "ios", "brand": "MY_BRAND" } ``` ```ts const response = await fetch('https://dev.cobru.co/user/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': process.env.COBRU_API_KEY!, }, body: JSON.stringify(userPayload), }); const createdUser = await response.json(); console.log(createdUser.username); ``` ```python import requests response = requests.post( "https://dev.cobru.co/user/", headers={ "x-api-key": COBRU_API_KEY, "Content-Type": "application/json", }, json=user_payload, ) print(response.json()) ``` ```php request('POST', 'https://dev.cobru.co/user/', [ 'headers' => [ 'x-api-key' => getenv('COBRU_API_KEY'), 'Content-Type' => 'application/json', ], 'json' => $userPayload, ]); $createdUser = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR); var_dump($createdUser); ``` Reglas de integración [#reglas-de-integración] La doc legacy indica que la request envía un `username` plano, mientras Cobru puede responder con un username persistido al que se le aplica el prefijo `brand`. No asumas que el valor enviado y el almacenado serán idénticos. Categoría y subcategoría deben tratarse como taxonomía server-driven. Siempre consúltalas antes del registro en lugar de hard-codear IDs en el cliente. El payload de onboarding menciona un array `documents` con IDs y URLs. Diseña un flujo de upload controlado y no asumas que Cobru almacenará URLs externas arbitrarias de forma indefinida. Recomendaciones UX [#recomendaciones-ux] * anticipa el siguiente paso antes de redirigir al usuario * incluye tu propio identificador de referencia en el `callback` * guarda `pk`, `url` e `idempotency_key` de Cobru * diseña una return URL que explique estado y siguientes acciones * documenta UX específica por método de pago, especialmente BRE-B y QR --- # Bancos disponibles Locale: es URL: https://docs.cobru.co/es/docs/api/bank-withdrawals/banks-list La lista de bancos para retiros a terceros aparece documentada en materiales legacy de Cobru, mientras que una variante más nueva basada en país aparece en exports adicionales. Confirma cuál es la vigente para tu integración. Endpoint mejor conocido [#endpoint-mejor-conocido] `GET /bank_list_third_party_withdraw/` Campos de respuesta vistos en documentación antigua [#campos-de-respuesta-vistos-en-documentación-antigua] | Field | Tipo | Notas | | ------ | -------- | -------------------------------- | | `id` | `number` | Identificador interno del banco. | | `name` | `string` | Nombre legible del banco. | Variante más nueva mencionada en materiales adicionales [#variante-más-nueva-mencionada-en-materiales-adicionales] Algunos exports más recientes también referencian: `GET /bank_list/?country={country_code}` Trata esa variante parametrizada por país como un posible contrato más nuevo hasta que Cobru la confirme. --- # Transferencia BRE-B Locale: es URL: https://docs.cobru.co/es/docs/api/bank-withdrawals/bre-b BRE-B aparece en la superficie de Cobru de dos formas distintas: 1. como método de pago dentro de `POST /cobru/` 2. como capacidad de transferencia o retiro dentro de la familia de retiros bancarios El flujo de pago por QR se entiende mucho mejor que el contrato de retiro. Verifica con Cobru el endpoint BRE-B específico antes de implementarlo. Endpoint candidato mejor conocido [#endpoint-candidato-mejor-conocido] `POST /withdraw/co/` Para qué sirve esta página [#para-qué-sirve-esta-página] Usa esta página cuando tu producto necesite mover fondos a un destino bancario en Colombia usando una capacidad de retiro o transferencia ligada a BRE-B, en lugar de cobrar un pago a través de un checkout Cobru. Lo que todavía falta confirmar [#lo-que-todavía-falta-confirmar] * path final y forma exacta del request * identificadores destino soportados para el beneficiario * si los retiros BRE-B comparten el mismo modelo de estados que otros retiros bancarios * si callbacks o webhooks entregan eventos finales de liquidación --- # Retiro a Argentina Locale: es URL: https://docs.cobru.co/es/docs/api/bank-withdrawals/create-argentina Este flujo transfronterizo está documentado desde exports legacy de Cobru. Revalídalo con Cobru antes de lanzar una experiencia de payouts para Argentina. Endpoint [#endpoint] `POST /withdraw/ar/` Campos del request vistos en documentación legacy [#campos-del-request-vistos-en-documentación-legacy] | Field | Tipo | Requerido | Notas | | ----------------- | -------- | ----------- | ------------------------------------------------ | | `amount` | `number` | sí | Monto del retiro. | | `currency_code` | `string` | sí | Los materiales legacy documentan `ARS`. | | `bank_name` | `string` | sí | Nombre del banco destino. | | `cbu` | `string` | condicional | Identificador bancario tradicional en Argentina. | | `cvu` | `string` | condicional | Identificador de cuenta virtual cuando aplique. | | `account_phone` | `string` | sí | Teléfono del beneficiario. | | `account_email` | `string` | sí | Email del beneficiario. | | `callback` | `string` | no | URL opcional de callback. | | `idempotency_key` | `string` | no | Clave opcional de idempotencia. | | `description` | `string` | no | Nota opcional del payout. | | `platform` | `string` | no | Valor opcional de origen o plataforma. | Notas de producción [#notas-de-producción] * Confirma si Cobru espera `cbu`, `cvu` o ambos dependiendo del riel del beneficiario. * Valida supuestos de FX y tiempos de payout antes de exponer este flujo a clientes. --- # Retiro a Brasil Locale: es URL: https://docs.cobru.co/es/docs/api/bank-withdrawals/create-brazil Este flujo transfronterizo está documentado desde exports legacy de Cobru. Revalídalo en sandbox antes de usarlo para payouts de producción. Endpoint [#endpoint] `POST /withdraw/br/` Campos del request vistos en documentación legacy [#campos-del-request-vistos-en-documentación-legacy] | Field | Tipo | Requerido | Notas | | ----------------- | -------- | ----------- | --------------------------------------------------------------- | | `amount` | `number` | sí | Monto del retiro. | | `currency_code` | `string` | sí | Los materiales legacy documentan `BRL`. | | `pix_key` | `string` | sí | Valor de la PIX key. | | `pix_key_type` | `string` | sí | Tipo de PIX key. | | `cpf` | `string` | condicional | Identificador tributario si el beneficiario es persona natural. | | `cnpj` | `string` | condicional | Identificador tributario si el beneficiario es empresa. | | `account_phone` | `string` | sí | Teléfono del beneficiario. | | `account_email` | `string` | sí | Email del beneficiario. | | `callback` | `string` | no | URL opcional de callback. | | `idempotency_key` | `string` | no | Clave opcional de idempotencia. | | `description` | `string` | no | Nota opcional del payout. | | `platform` | `string` | no | Identificador opcional de plataforma u origen. | | `longitude` | `number` | no | Campo geográfico opcional visto en exports antiguos. | | `latitude` | `number` | no | Campo geográfico opcional visto en exports antiguos. | Notas de producción [#notas-de-producción] * Confirma moneda, schema del beneficiario, modelo FX, estructura de fees y tiempos de settlement con Cobru. * Valida `pix_key_type` y requisitos de CPF/CNPJ antes de enviar el request. --- # Retiro a México Locale: es URL: https://docs.cobru.co/es/docs/api/bank-withdrawals/create-mexico Este flujo transfronterizo está documentado desde exports legacy de Cobru. Revalídalo con Cobru antes de usarlo en producción. Endpoint [#endpoint] `POST /withdraw/mx/` Campos del request vistos en documentación legacy [#campos-del-request-vistos-en-documentación-legacy] | Field | Tipo | Requerido | Notas | | ----------------- | -------- | --------- | --------------------------------------- | | `amount` | `number` | sí | Monto del retiro. | | `currency_code` | `string` | sí | Los materiales legacy documentan `MXN`. | | `clabe` | `string` | sí | CLABE estándar del banco en México. | | `beneficiary` | `string` | sí | Nombre del beneficiario. | | `account_phone` | `string` | sí | Teléfono del beneficiario. | | `account_email` | `string` | sí | Email del beneficiario. | | `callback` | `string` | no | URL opcional de callback. | | `idempotency_key` | `string` | no | Clave opcional de idempotencia. | | `description` | `string` | no | Nota opcional del payout. | | `platform` | `string` | no | Valor opcional de plataforma u origen. | Notas de producción [#notas-de-producción] * Confirma validaciones de CLABE, moneda de settlement y modos de falla con Cobru. * Haz explícita la validación del beneficiario en tu propia UI antes de enviar el payout. --- # Crear retiro Locale: es URL: https://docs.cobru.co/es/docs/api/bank-withdrawals/create Esta página documenta el contrato mejor conocido para retiros a terceros en Colombia a partir de exports legacy de Cobru. Revalida el comportamiento exacto en sandbox antes de convertirlo en una dependencia de producción. Endpoint [#endpoint] `POST /thirdpartywithdraw/` Campos del request vistos en documentación legacy [#campos-del-request-vistos-en-documentación-legacy] | Field | Tipo | Requerido | Notas | | ------------------------------ | -------- | --------- | ----------------------------------------------------------- | | `amount` | `number` | sí | Monto del retiro. | | `account_holder_name` | `string` | sí | Nombre completo del beneficiario. | | `account_type` | `string` | sí | Tipo de cuenta aceptado por el banco destino. | | `account_holder_document` | `string` | sí | Documento del beneficiario. | | `account_holder_document_type` | `string` | sí | Código de tipo de documento esperado por Cobru. | | `account_number` | `string` | sí | Número de cuenta destino. | | `account_phone` | `string` | sí | Teléfono del beneficiario. | | `account_email` | `string` | sí | Email del beneficiario. | | `bank_name` | `string` | no | Nombre o descriptor del banco cuando sea requerido. | | `description` | `string` | no | Nota opcional del payout o descripción interna. | | `callback` | `string` | no | URL opcional para actualizaciones de estado. | | `idempotency_key` | `string` | no | Campo mejor documentado para deduplicar intentos de payout. | Qué debes confirmar con Cobru antes de salir a producción [#qué-debes-confirmar-con-cobru-antes-de-salir-a-producción] * si `bank_name` debe reemplazarse hoy por un bank code o bank ID * valores aceptados de `account_type` y `account_holder_document_type` * si los callbacks siguen soportados o fueron reemplazados por webhooks * tiempos de settlement y estados terminales del payout Señales de error vistas en materiales antiguos [#señales-de-error-vistas-en-materiales-antiguos] | Señal | Significado | | ------ | ---------------------------------------------------- | | `R010` | Datos bancarios inválidos o rechazo de validación. | | `P002` | Falla de procesamiento o del proveedor. | | `E001` | Error genérico de validación o proveedor downstream. | Notas de producción [#notas-de-producción] * Envía siempre una `idempotency_key` si Cobru confirma que sigue soportada. * Guarda el identificador del retiro retornado por Cobru para reconciliar cambios de estado. * Trata los retiros bancarios como asíncronos incluso si la respuesta inicial es exitosa. --- # Detalles del retiro Locale: es URL: https://docs.cobru.co/es/docs/api/bank-withdrawals/details Esta vista de detalle está documentada desde materiales legacy de payouts Cobru y todavía requiere validación fresca desde un ambiente real. Endpoint [#endpoint] `GET /thirdpartywithdraw/{id}` Parámetro de path [#parámetro-de-path] | Field | Tipo | Descripción | | ----- | -------- | ------------------------------------------- | | `id` | `number` | Identificador del retiro bancario en Cobru. | Qué deberías esperar [#qué-deberías-esperar] Usa este endpoint para recuperar el estado más reciente del payout y el registro final de liquidación bancaria para un retiro específico. Los materiales antiguos sugieren que la respuesta replica la mayoría de campos del listado, pero acotados a un solo payout. --- # Retiros a bancos Locale: es URL: https://docs.cobru.co/es/docs/api/bank-withdrawals Esta familia mezcla varios niveles de evidencia: contratos legacy de retiros a terceros en Colombia, exports más nuevos por país y visibilidad en el menú del producto. Trata cada página de endpoint con un nivel de confianza distinto y valida el flujo exacto que vayas a desplegar. El menú API de Cobru expone una superficie amplia de retiros bancarios para Colombia y otros países. Es la familia principal cuando los fondos deben salir de Cobru y liquidarse en una cuenta bancaria del beneficiario, no en otra wallet Cobru. Cuándo usar retiros a bancos [#cuándo-usar-retiros-a-bancos] * desembolsar fondos a cuentas bancarias de beneficiarios * construir flujos operativos de payout para comercios, usuarios o tesorería * soportar rieles país-específicos como Colombia, Brasil, Argentina, México o movimiento bancario ligado a BRE-B Cobertura visible hoy [#cobertura-visible-hoy] | Operación | Método | Path | Confianza | | --------------------------- | ------ | ---------------------------------- | ----------------- | | lista de bancos disponibles | `GET` | `/bank_list_third_party_withdraw/` | legacy-doc | | tus retiros | `GET` | `/thirdpartywithdraw/` | legacy-doc | | crear retiro a Colombia | `POST` | `/thirdpartywithdraw/` | legacy-doc | | detalle del retiro | `GET` | `/thirdpartywithdraw/{id}` | legacy-doc | | cancelar retiro | `POST` | `/cancelthirdpartywithdraw/` | legacy-doc | | transferencia BRE-B | `POST` | `/withdraw/co/` | menú más research | | crear retiro a Brasil | `POST` | `/withdraw/br/` | legacy-doc | | crear retiro a México | `POST` | `/withdraw/mx/` | legacy-doc | | crear retiro a Argentina | `POST` | `/withdraw/ar/` | legacy-doc | Flujo de retiro [#flujo-de-retiro] Resuelve primero el riel del beneficiario, normalmente consultando bancos soportados o validando el identificador país-específico como PIX, CBU/CVU o CLABE. Crea el retiro con identidad del beneficiario, datos bancarios, monto y campos opcionales de idempotencia o callback cuando estén documentados. Reconcilia el payout de forma asíncrona desde los endpoints de listado y detalle. No asumas que el retiro bancario liquida al instante. Temas comunes que debes resolver temprano [#temas-comunes-que-debes-resolver-temprano] * KYC del beneficiario y mapeo de tipos de documento * idempotencia para reintentos * garantías de entrega de callbacks o webhooks * fees, FX y monto final liquidado * manejo de rechazos por país y por riel bancario --- # Tus retiros Locale: es URL: https://docs.cobru.co/es/docs/api/bank-withdrawals/list Este listado proviene de materiales legacy de payouts Cobru. Filtros, paginación y segmentación por país todavía requieren validación en vivo. Endpoint [#endpoint] `GET /thirdpartywithdraw/` Campos vistos en respuestas legacy [#campos-vistos-en-respuestas-legacy] | Field | Tipo | Notas | | ---------------- | -------- | -------------------------------------------- | | `type` | `string` | Tipo de retiro o identificador del riel. | | `pk` | `number` | Identificador del payout en Cobru. | | `state` | `string` | Estado del payout. | | `amount` | `number` | Monto solicitado. | | `payed_amount` | `number` | Monto neto pagado después de fees y ajustes. | | `fee` | `number` | Fee de Cobru. | | `fee_iva` | `number` | IVA aplicado a las fees. | | `gmf` | `number` | GMF cuando aplique. | | `account_number` | `string` | Número de cuenta destino. | | `description` | `string` | Descripción opcional del payout. | | `date_created` | `string` | Timestamp de creación. | | `date_consigned` | `string` | Fecha de consignación cuando exista. | | `date_deposited` | `string` | Fecha de depósito final cuando exista. | | `date_rejected` | `string` | Fecha de rechazo cuando exista. | Comportamiento adicional visto en documentación antigua [#comportamiento-adicional-visto-en-documentación-antigua] Los materiales legacy también mencionan consultar el listado por `idempotency_key` para encontrar un intento de payout previamente enviado. --- # API de autenticación Locale: es URL: https://docs.cobru.co/es/docs/api/authentication La API de Cobru usa un modelo por capas: * `x-api-key` * `Authorization: Bearer {access}` Endpoint disponible [#endpoint-disponible] | Endpoint | Método | Estado | | ----------------- | ------ | ------------------------------------------------ | | `/token/refresh/` | `POST` | verificado contra comportamiento real de sandbox | Notas para implementadores [#notas-para-implementadores] * El campo del body es `refresh`, no `refresh_token`. * Mantén la API key, el refresh token y el access token del lado del servidor. * Cachea el access token máximo 50 minutos. Continúa con `Refresh token` para el detalle completo del request y response. --- # Refresh token Locale: es URL: https://docs.cobru.co/es/docs/api/authentication/refresh Endpoint [#endpoint] `POST /token/refresh/` Verificado contra sandbox y contra los learnings internos de integración. Headers [#headers] ```http x-api-key: {tu_api_key} Content-Type: application/json ``` Body [#body] ```json { "refresh": "tu_refresh_token" } ``` Response [#response] ```json { "access": "eyJ0eXAi..." } ``` curl [#curl] ```bash curl -X POST https://dev.cobru.co/token/refresh/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Content-Type: application/json" \ -d '{"refresh":"'"$COBRU_REFRESH_TOKEN"'"}' ``` Node.js [#nodejs] ```ts const response = await fetch('https://dev.cobru.co/token/refresh/', { method: 'POST', headers: { 'x-api-key': process.env.COBRU_API_KEY!, 'Content-Type': 'application/json', }, body: JSON.stringify({ refresh: process.env.COBRU_REFRESH_TOKEN, }), }); const data = await response.json(); ``` Python [#python] ```python import os import requests response = requests.post( "https://dev.cobru.co/token/refresh/", headers={ "x-api-key": os.environ["COBRU_API_KEY"], "Content-Type": "application/json", }, json={"refresh": os.environ["COBRU_REFRESH_TOKEN"]}, ) data = response.json() ``` --- # Crear tarjeta Locale: es URL: https://docs.cobru.co/es/docs/api/cards/create La emisión de tarjetas está documentada desde exports legacy de Cobru. Revalida el comportamiento del emisor y el manejo PCI antes de lanzar un programa de tarjetas en vivo. Endpoint [#endpoint] `POST /cobru/debit/create_and_reload_card/` Body mejor conocido [#body-mejor-conocido] La creación de tarjeta está documentada como una llamada al endpoint compartido de create-and-reload con un monto de `0`. ```json { "amount": 0 } ``` Campos de respuesta vistos en documentación legacy [#campos-de-respuesta-vistos-en-documentación-legacy] | Field | Tipo | Notas | | -------------------- | -------- | -------------------------------------------- | | `balance` | `number` | Balance actual de la tarjeta. | | `cvv` | `string` | Código de seguridad. | | `display_expiration` | `string` | Expiración legible para humanos. | | `id` | `number` | Identificador de la tarjeta. | | `masked_pan` | `string` | Número de tarjeta enmascarado. | | `max_balance` | `number` | Balance máximo permitido. | | `state` | `string` | Estado de la tarjeta. | | `support_token` | `string` | Token de soporte o referencia del proveedor. | Preguntas que debes resolver antes de un rollout completo [#preguntas-que-debes-resolver-antes-de-un-rollout-completo] * tipo de emisión: single-use o reusable * fuente de fondeo * requisitos de identidad del cardholder * alcance PCI y quién hospeda el PAN * expiración y comportamiento de freeze --- # Detalles y listado Locale: es URL: https://docs.cobru.co/es/docs/api/cards/details La recuperación de tarjetas está documentada desde exports legacy de Cobru. Confirma si detalle y listado siguen siendo variantes del mismo endpoint en el producto actual. Endpoint mejor conocido [#endpoint-mejor-conocido] `GET /cobru/debit/get_card/` Comportamiento de query visto en docs antiguas [#comportamiento-de-query-visto-en-docs-antiguas] * llamar sin `card_id` para listar tarjetas * pasar `?card_id={card_id}` para recuperar una tarjeta Campos vistos en respuestas legacy [#campos-vistos-en-respuestas-legacy] | Field | Tipo | Notas | | -------------------- | -------- | ------------------------------ | | `id` | `number` | Identificador de la tarjeta. | | `masked_pan` | `string` | Número de tarjeta enmascarado. | | `display_expiration` | `string` | Expiración legible. | | `balance` | `number` | Balance actual. | | `state` | `string` | Estado de la tarjeta. | --- # Congelar tarjeta Locale: es URL: https://docs.cobru.co/es/docs/api/cards/freeze Congelar y descongelar está documentado desde exports legacy de Cobru. Confirma reversibilidad y efecto sobre autorizaciones pendientes antes de exponer esta función al usuario final. Endpoint [#endpoint] `POST /cobru/debit/freeze_card/` Campos del request vistos en documentación legacy [#campos-del-request-vistos-en-documentación-legacy] | Field | Tipo | Requerido | Notas | | --------- | --------- | --------- | ----------------------------------------------- | | `card_id` | `number` | sí | Identificador de la tarjeta. | | `freeze` | `boolean` | sí | `true` para congelar, `false` para descongelar. | --- # Tarjetas virtuales Locale: es URL: https://docs.cobru.co/es/docs/api/cards La familia de tarjetas está respaldada por exports legacy de Cobru, no por un contrato público recién verificado. La superficie de endpoints es significativa, pero igual debes validar comportamiento del emisor, alcance PCI y estados operativos antes del lanzamiento. El menú API de Cobru incluye una sección `Tarjetas`, lo que sugiere una capacidad más amplia de tarjetas programables montada sobre la infraestructura de wallet y saldo. Elige un workflow de tarjetas [#elige-un-workflow-de-tarjetas] Operaciones visibles [#operaciones-visibles] | Operación | Método | Path | Confianza | | ------------------ | ------ | -------------------------------------- | ---------- | | crear tarjeta | `POST` | `/cobru/debit/create_and_reload_card/` | legacy-doc | | recargar tarjeta | `POST` | `/cobru/debit/create_and_reload_card/` | legacy-doc | | detalles y listado | `GET` | `/cobru/debit/get_card/` | legacy-doc | | movimientos | `GET` | `/cobru/debit/get_transactions/` | legacy-doc | | congelar tarjeta | `POST` | `/cobru/debit/freeze_card/` | legacy-doc | Restricciones de lanzamiento [#restricciones-de-lanzamiento] * confirma SLA del emisor y ownership operativo antes de habilitar tarjetas para clientes * mapea reglas de acceso PCI, PII y soporte antes de exponer datos de tarjeta en tooling interno * trata freeze y unfreeze como acciones de alta sensibilidad con audit logs --- # Movimientos Locale: es URL: https://docs.cobru.co/es/docs/api/cards/movements El historial de movimientos está documentado desde exports legacy de Cobru. Confirma paginación y semántica de movimientos posteados vs pendientes antes de construir lógica de conciliación sobre este endpoint. Endpoint mejor conocido [#endpoint-mejor-conocido] `GET /cobru/debit/get_transactions/?card_id={card_id}` Parámetros de query vistos en documentación legacy [#parámetros-de-query-vistos-en-documentación-legacy] | Field | Tipo | Requerido | Notas | | ---------- | -------- | --------- | ---------------------------- | | `card_id` | `number` | sí | Identificador de la tarjeta. | | `per_page` | `number` | no | Tamaño de página opcional. | | `page_num` | `number` | no | Número de página opcional. | --- # Recargar tarjeta Locale: es URL: https://docs.cobru.co/es/docs/api/cards/topup La recarga de tarjeta está documentada desde exports legacy de Cobru. Revalida tiempos de settlement y comportamiento del endpoint compartido antes de usarlo en producción. Endpoint [#endpoint] `POST /cobru/debit/create_and_reload_card/` Campos del request vistos en documentación legacy [#campos-del-request-vistos-en-documentación-legacy] | Field | Tipo | Requerido | Notas | | --------- | -------- | --------- | -------------------------------------- | | `amount` | `number` | sí | Saldo que se agregará a la tarjeta. | | `card_id` | `number` | sí | Identificador de la tarjeta existente. | Nota importante de implementación [#nota-importante-de-implementación] Los materiales antiguos describen creación y recarga como dos modos de un mismo endpoint. Trata ese comportamiento compartido como real hasta que Cobru confirme un contrato nuevo separado. --- # Cancelar retiro Locale: es URL: https://docs.cobru.co/es/docs/api/cash-withdrawals/cancel La cancelación está documentada en materiales legacy de Cobru, pero debes validar en vivo la ventana de cancelación y los side effects del proveedor antes de exponerla a clientes. Endpoint [#endpoint] `POST /cancelcashwithdraw/` Campos del request [#campos-del-request] | Field | Tipo | Requerido | Notas | | ----- | -------- | --------- | ------------------------------------------------------------ | | `id` | `number` | sí | Identificador del retiro en efectivo que se quiere cancelar. | Ejemplo de body [#ejemplo-de-body] ```json { "id": 123456 } ``` Notas operativas [#notas-operativas] * Solo expón la cancelación mientras el retiro siga pendiente o en un estado cancelable. * Refresca el detalle o el listado después de cancelar para reconciliar el estado final. * Mantén el identificador del retiro de Cobru disponible en tus herramientas internas de operaciones. --- # Retirar efectivo Locale: es URL: https://docs.cobru.co/es/docs/api/cash-withdrawals/create Este contrato se basa en materiales legacy de Cobru para retiros por Efecty. Valida el nombre del proveedor, el comportamiento de callbacks y el contrato final de errores en sandbox antes de usarlo en producción. Endpoint [#endpoint] `POST /cashwithdraw/` Campos del request [#campos-del-request] | Field | Tipo | Requerido | Notas | | ---------- | --------- | --------- | ------------------------------------------------------------------------------------ | | `method` | `string` | sí | Selector del proveedor mejor documentado. Los materiales legacy muestran `efecty`. | | `document` | `string` | sí | Número de documento del destinatario. | | `amount` | `number` | sí | Monto solicitado para el payout. | | `exp_days` | `number` | sí | Días hasta que el retiro expire. | | `name` | `string` | sí | Nombre completo del destinatario en la solicitud. | | `coupon` | `string` | no | Cupón o beneficio opcional cuando esté soportado. | | `callback` | `string` | no | URL opcional para actualizaciones del resultado. | | `estimate` | `boolean` | no | Cuando es `true`, puede pedir una estimación en lugar de crear el retiro definitivo. | Ejemplo de body [#ejemplo-de-body] ```json { "amount": 10000, "document": "213232323", "estimate": false, "exp_days": 30, "method": "efecty", "name": "Testeo efecty" } ``` Ejemplo de respuesta [#ejemplo-de-respuesta] ```json { "status": "ok", "document": "213232323", "ref": 123456, "amount": 9700 } ``` Comportamiento de callback [#comportamiento-de-callback] Los materiales legacy muestran un campo `callback` en la creación y en el listado. Trata la entrega de callbacks como una integración operativa opcional hasta que Cobru confirme: * política de reintentos * modelo de firma o verificación * estados terminales que disparan callbacks Señales de error vistas en materiales antiguos [#señales-de-error-vistas-en-materiales-antiguos] | Respuesta | Significado | | ------------------------------------ | ------------------------------------------------ | | `400 {"error":"not enough balance"}` | El saldo del emisor es insuficiente. | | `200 {"error":"BAD_USER"}` | Falló la validación del usuario. | | `200 {"error":"EXPIRED"}` | El cupón o beneficio expiró. | | `200 {"error":"ALL_USED"}` | El cupón o beneficio ya fue consumido. | | `200 {"error":"NOT_FOUND"}` | No se encontró el cupón u objeto referenciado. | | `400 {"message":"unknown method"}` | El proveedor o método de retiro no es soportado. | Notas de producción [#notas-de-producción] * Reconcilia el monto neto retornado por Cobru, no solo el monto solicitado, porque las fees pueden afectar el payout final. * No asumas que todo retiro creado queda disponible de inmediato para cobro; diseña para comportamiento asíncrono del proveedor. * Si expones cancelación, guarda los identificadores de referencia de Cobru desde el momento de la creación. --- # Detalles del retiro Locale: es URL: https://docs.cobru.co/es/docs/api/cash-withdrawals/details Los materiales legacy y las capturas del producto indican una vista de detalle para retiros en efectivo, pero el contrato exacto todavía necesita verificación fresca. Endpoint [#endpoint] `GET /cashwithdraw/{id}` Parámetro de path [#parámetro-de-path] | Field | Tipo | Descripción | | ----- | -------- | -------------------------------------------------------------------------------------------- | | `id` | `number` | Identificador del retiro en efectivo en Cobru, normalmente expuesto como `pk` en el listado. | Uso esperado [#uso-esperado] * obtener el estado más reciente antes de mostrar instrucciones de cobro * validar si el retiro sigue siendo cancelable antes de llamar el endpoint de cancelación * inspeccionar referencias del proveedor cuando soporte necesite depurar el payout --- # Retiros en efectivo Locale: es URL: https://docs.cobru.co/es/docs/api/cash-withdrawals La familia de retiros en efectivo está documentada en su mayoría desde materiales legacy de Cobru. El flujo de Efecty es el contrato público mejor conocido, pero debes revalidar cobertura de proveedor, ventana de cancelación y comportamiento de callbacks antes de desplegarlo. Cobru expone una familia de retiros en efectivo bajo `Retiros en efectivo`. Esta superficie es útil cuando necesitas una opción de payout que no dependa de una cuenta bancaria destino. Cuándo usar retiros en efectivo [#cuándo-usar-retiros-en-efectivo] * payouts con cobro en efectivo para destinatarios sin cuenta bancaria * desembolsos asistidos desde soporte u operaciones * experiencias de fallback cuando los rieles bancarios no están disponibles Endpoints [#endpoints] | Endpoint | Método | Path | Estado | | --------------------------- | ------ | ---------------------- | ------------------------------------ | | retirar dinero por efectivo | `POST` | `/cashwithdraw/` | documentado en materiales legacy | | obtener retiros | `GET` | `/cashwithdraw/` | documentado en materiales legacy | | detalles del retiro | `GET` | `/cashwithdraw/{id}` | materiales legacy y menú de producto | | cancelar retiro | `POST` | `/cancelcashwithdraw/` | documentado en materiales legacy | Ciclo de vida del retiro [#ciclo-de-vida-del-retiro] Crea el retiro con la identidad del destinatario, monto, método de pago y reglas de expiración. Sigue el retiro desde el endpoint de listado o detalle hasta que llegue a un estado terminal como pagado, rechazado o expirado. Cancela el retiro antes del cobro cuando el flujo de negocio o la solicitud del cliente lo requieran y el payout siga siendo cancelable. Restricciones conocidas [#restricciones-conocidas] * Los ejemplos públicos están centrados en `efecty`. * Los materiales legacy describen soporte para `callback`, pero el contrato exacto de entrega aún requiere validación fresca. * Existen semánticas de estado en exports antiguos, pero deben confirmarse contra un ambiente real antes de codificar reglas de negocio sobre ellas. --- # Obtener retiros Locale: es URL: https://docs.cobru.co/es/docs/api/cash-withdrawals/list Este listado está documentado desde materiales legacy de Cobru, pero filtros y paginación todavía deben validarse en vivo. Endpoint [#endpoint] `GET /cashwithdraw/` Campos vistos en respuestas legacy [#campos-vistos-en-respuestas-legacy] | Field | Tipo | Notas | | ----------------- | -------- | -------------------------------------------------- | | `amount` | `number` | Monto solicitado del retiro. | | `date` | `string` | Fecha de creación o timestamp del proveedor. | | `from_user` | `string` | Identificador del usuario origen. | | `from_user_phone` | `string` | Teléfono del emisor. | | `pk` | `number` | Identificador del retiro en Cobru. | | `to_user` | `string` | Descriptor del destinatario o nombre del receptor. | | `method` | `string` | Nombre del proveedor, por ejemplo `efecty`. | | `state` | `number` | Código de estado del retiro. | | `callback` | `string` | URL de callback asociada al request cuando exista. | Modelo de estados visto en exports antiguos [#modelo-de-estados-visto-en-exports-antiguos] | Estado | Significado | | ------ | ----------- | | `0` | pendiente | | `1` | procesando | | `2` | pagado | | `3` | rechazado | | `4` | cancelado | | `5` | expirado | --- # Celo Locale: es URL: https://docs.cobru.co/es/docs/api/celo El soporte Celo está documentado a partir de materiales legacy de Spotlight y debe tratarse como una capability avanzada o beta hasta volver a validarla. Qué expone Cobru [#qué-expone-cobru] Los materiales originales de Cobru describen una superficie Celo / cUSD con estas operaciones: * crear u obtener una billetera con `GET /celo/` * transferir cUSD con `POST /celo/` * recuperar datos de exportación de cuenta con `POST /celo/account/` * listar transacciones de la billetera con `GET /celo/transactions/cusd/` * estimar o comprar cUSD en flujos auxiliares relacionados Audiencia recomendada [#audiencia-recomendada] Solo deberías construir sobre esta superficie si tu producto realmente necesita: * visibilidad de settlement sobre blockchain * operaciones de tesorería en cUSD * transferencias entre cuentas administradas por Cobru Para checkout estándar, PSE, BRE-B o QR, empieza por Cobrus. Ejemplo: obtener o crear la billetera [#ejemplo-obtener-o-crear-la-billetera] ```bash curl -X GET https://dev.cobru.co/celo/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Authorization: Bearer $COBRU_ACCESS_TOKEN" ``` ```ts const response = await fetch('https://dev.cobru.co/celo/', { method: 'GET', headers: { 'x-api-key': process.env.COBRU_API_KEY!, Authorization: `Bearer ${accessToken}`, }, }); const wallet = await response.json(); console.log(wallet.address, wallet.balance); ``` ```python import requests response = requests.get( "https://dev.cobru.co/celo/", headers={ "x-api-key": COBRU_API_KEY, "Authorization": f"Bearer {access_token}", }, ) print(response.json()) ``` ```php request('GET', 'https://dev.cobru.co/celo/', [ 'headers' => [ 'x-api-key' => getenv('COBRU_API_KEY'), 'Authorization' => 'Bearer ' . $accessToken, ], ]); $wallet = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR); var_dump($wallet); ``` Advertencias operativas [#advertencias-operativas] La documentación legacy menciona un flujo que devuelve las 24 palabras mnemonic para recuperar la billetera. Trátalo como material extremadamente sensible. No lo logs, no lo persistas sin controles estrictos ni lo expongas a herramientas de soporte. Los docs históricos mencionan explorers de Alfarojes y mainnet. Confirma red, explorer y comportamiento por ambiente antes de mostrar links de exploración a usuarios finales. Si soportas cUSD, crea runbooks operativos para export de wallet, recuperación de fallas en transferencias y conciliación financiera antes de habilitarlo para clientes. Documentación relacionada [#documentación-relacionada] Inspecciona los endpoints y schemas de Celo en la referencia interactiva. Diseña flujos de tesorería y balance sobre el modelo general de cuenta Cobru. --- # Botón Bancolombia Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/bancolombia-button Endpoint [#endpoint] `POST /{url}` Request [#request] ```json { "name": "Test Gómez", "payment": "bancolombia_transfer", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC" } ``` Siguiente paso [#siguiente-paso] Spotlight indica que la respuesta contiene un `checkout` URL que el usuario debe abrir para completar el pago. --- # Bre-B Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/breb Endpoint [#endpoint] `POST /{url}` Request [#request] ```json { "payment": "breb" } ``` Esta es la variante más mínima de `payment-details` documentada en Spotlight. Spotlight documenta `payment: "breb"` directo, pero el research posterior en sandbox observó esta ruta como deshabilitada o restringida comercialmente en algunos entornos. Confirma la disponibilidad directa de Bre-B en tu propio sandbox antes de tratarla como lista para producción. Qué esperar en la respuesta [#qué-esperar-en-la-respuesta] Spotlight muestra una respuesta de `paymentorder` que incluye: * `qr_value` * `key_value` * `method: "breb"` * `franchise: "breb"` Los materiales originales también indican que `qr_value` y `key_value` expiran en 5 minutos. Cuándo usarlo [#cuándo-usarlo] Usa Bre-B cuando quieras una opción de transferencia interoperable y tu producto pueda trabajar con instrucciones de pago de vida corta más confirmación por webhook. --- # Pagos en efectivo Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/cash-payments Endpoint [#endpoint] `POST /{url}` Literales soportados de `payment` [#literales-soportados-de-payment] * `efecty` * `corresponsal_bancolombia` Spotlight también menciona rieles en efectivo como Baloto en ejemplos más antiguos, pero los requests más claros están para Efecty y Corresponsal Bancolombia. Ejemplo de request [#ejemplo-de-request] ```json { "name": "Juan Perez", "payment": "efecty", "cc": "1140867070", "email": "juan@cobru.co", "document_type": "CC", "phone": "3002794981" } ``` La forma del request para `corresponsal_bancolombia` es la misma; solo cambia el literal `payment`. --- # Consultar un cobru Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/consult Endpoint [#endpoint] `GET /cobru_detail/{url}` Este endpoint está documentado en materiales legacy de Cobru. Antes se creía que no existía, así que conviene revalidarlo en tu propia cuenta sandbox antes de usarlo como dependencia crítica. Campos observados en la documentación legacy [#campos-observados-en-la-documentación-legacy] * identidad del pagador * `payment_method` * `state` * `payment_method_enabled` * `amount` * `description` * `payed_amount` * fees y fechas Ejemplo de respuesta [#ejemplo-de-respuesta] ```json { "fee_amount": 6383, "payer_id": "10000000", "payer_name": "Juan Plata", "payment_method": "efecty", "state": 1, "payer_email": "juan@cobru.com", "url": "ufa8q176", "amount": 107595, "description": "description", "payed_amount": 100000 } ``` --- # Crear un cobru Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/create Endpoint [#endpoint] `POST /cobru/` Verificado en sandbox. Hoy es el flujo Cobru mejor entendido y más cercano a producción. Campos requeridos [#campos-requeridos] ```json { "amount": 50000, "description": "Orden #123", "expiration_days": 1, "client_assume_costs": false, "iva": 0, "payment_method_enabled": "{\"breb\":true,\"pse\":true,\"NEQUI\":true}", "payer_redirect_url": "https://tuapp.com/pago-exitoso", "callback": "https://tuapp.com/api/cobru/webhook" } ``` Quirks conocidos [#quirks-conocidos] | Quirk | Detalle | Fix | | -------------------------------- | ----------------------- | ------------------------------------------------ | | tipo de `payment_method_enabled` | debe ser un string JSON | usar `JSON.stringify()` | | faltan redirect URLs | devuelve `403` engañoso | enviar siempre `payer_redirect_url` y `callback` | | `url` en response | solo slug corto | construir `{baseUrl}/{url}` manualmente | | `amount` en response | string con decimales | parsearlo antes de operar | Flags comunes de métodos de pago [#flags-comunes-de-métodos-de-pago] ```json { "cobru": true, "pse": true, "bancolombia_transfer": true, "credit_card": true, "NEQUI": true, "dale": true, "efecty": true, "corresponsal_bancolombia": true, "BTC": false, "CUSD": false } ``` Ejemplo de respuesta [#ejemplo-de-respuesta] ```json { "pk": 27150, "amount": "50000.00", "state": 0, "url": "3gofdf6f", "payed_amount": "47605.00", "fee_amount": 2395, "idempotency_key": "3114242222_8de7c88b84...", "currency_code": "COP" } ``` curl [#curl] ```bash curl -X POST https://dev.cobru.co/cobru/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Authorization: Bearer $COBRU_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "amount": 50000, "description": "Orden #123", "expiration_days": 1, "client_assume_costs": false, "iva": 0, "payment_method_enabled": "{\"breb\":true,\"pse\":true}", "payer_redirect_url": "https://tuapp.com/pago-exitoso", "callback": "https://tuapp.com/api/cobru/webhook" }' ``` --- # Tarjeta de crédito Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/credit-card Endpoint [#endpoint] `POST /{url}` Request [#request] ```json { "name": "Test Gómez", "payment": "credit_card", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC", "credit_card": "4111111111111111", "expiration_date": "12/30", "cvv": "123", "dues": 1 } ``` Notas de Spotlight [#notas-de-spotlight] * Cobru no persiste los datos de la tarjeta * en producción el tráfico debe ser HTTPS * tarjetas de prueba mostradas por Spotlight: * aprobada: `4111 1111 1111 1111` * rechazada: `4111 1111 1111 1112` --- # dale! Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/dale Endpoint [#endpoint] `POST /{url}` Request [#request] ```json { "name": "Test Gómez", "payment": "dale", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC" } ``` --- # Daviplata Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/daviplata Paso 1 — Iniciar el pago [#paso-1--iniciar-el-pago] `POST /{url}` ```json { "name": "Test Gómez", "payment": "daviplata", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC" } ``` Paso 2 — Confirmar el OTP [#paso-2--confirmar-el-otp] Spotlight documenta un endpoint adicional: `POST /cobru/confirm_daviplata/` ```json { "URL": "ufa8q176", "OTP": "123456" } ``` Si todo sale bien, Spotlight describe una respuesta con `result == "OK"`. Cobru todavía no ha publicado una repetición completa del OTP de este paso dentro de la evidencia de sandbox que respalda este repo. Trátalo como un contrato legacy fuerte, no como un flujo verificado recientemente. --- # Editar un cobru Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/edit Endpoint [#endpoint] `POST /edit_cobru/` Documentado en materiales legacy de Cobru. Verifica en sandbox qué campos siguen siendo editables después de compartir o usar un pago. Campos vistos en documentación legacy [#campos-vistos-en-documentación-legacy] | Campo | Requerido | Propósito | | ----------------- | --------- | --------------------------------- | | `url` | sí | identificar el cobru a editar | | `description` | no | actualizar descripción | | `amount` | no | cambiar monto | | `expiration_days` | no | cambiar expiración | | `payment_methods` | no | actualizar métodos permitidos | | `fee_iva` | no | actualizar porcentaje de impuesto | Ejemplo de request [#ejemplo-de-request] ```json { "url": "xx17elpi", "description": "descripción actualizada", "amount": 80000, "expiration_days": 10 } ``` --- # Cobrus Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus Un "cobru" es el objeto de pago hosted de Cobru. Combina monto, descripción, métodos habilitados, expiración, URLs de retorno y el callback que reporta cambios de estado. Empieza aquí [#empieza-aquí] Orden recomendado [#orden-recomendado] 1. [Crear un cobru](/es/docs/api/cobrus/create) 2. [Enviar detalles de pago](/es/docs/api/cobrus/payment-details) 3. Páginas específicas por método como [Bre-B](/es/docs/api/cobrus/breb), [PSE](/es/docs/api/cobrus/pse) y [Nequi](/es/docs/api/cobrus/nequi) 4. [Consultar un cobru](/es/docs/api/cobrus/consult) 5. [Cotizar un cobru](/es/docs/api/cobrus/quote) o [Editar un cobru](/es/docs/api/cobrus/edit) solo si tu producto realmente necesita esos flujos Mapa de endpoints [#mapa-de-endpoints] | Familia de endpoint | Método | Estado de verificación | | ------------------------ | ------ | ----------------------------------------- | | Crear un cobru | `POST` | verificado | | Generar detalles de pago | `POST` | documentado en materiales legacy de Cobru | | Consultar un cobru | `GET` | documentado en materiales legacy de Cobru | | Bancos PSE | `GET` | documentado en materiales legacy de Cobru | | Cotizar un cobru | `POST` | documentado en materiales legacy de Cobru | | Editar un cobru | `POST` | documentado en materiales legacy de Cobru | Estados comunes [#estados-comunes] | Estado | Significado | | ------ | --------------------- | | `0` | Creado | | `1` | En proceso | | `2` | No pagado / rechazado | | `3` | Pagado | | `4` | Reembolsado | | `5` | Expirado | Notas operativas [#notas-operativas] * Trata la creación del pago y el estado final del pago como momentos separados dentro de tu sistema. * Guarda juntos `url`, `pk` y tu identificador interno de orden desde la primera escritura. * Si un flujo específico por método no está recién verificado, mantenlo detrás de una revisión operativa explícita antes del rollout amplio. --- # Nequi Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/nequi Endpoint [#endpoint] `POST /{url}` Request [#request] ```json { "name": "Test Gómez", "payment": "NEQUI", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC", "phone_nequi": "307654332", "push": true } ``` Comportamiento de `push` [#comportamiento-de-push] * `push: true` envía un push a la app Nequi del pagador * `push: false` evita el push y Spotlight dice que la respuesta incluye la data necesaria para una experiencia tipo QR, incluido `ref` --- # Enviar detalles de pago Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/payment-details Endpoint [#endpoint] `POST /{url}` Este contrato viene principalmente de los materiales originales de Spotlight de Cobru, notas internas compiladas de API y research posterior del checkout. Cobru todavía no ha reejecutado todas las variantes de método de punta a punta dentro de la evidencia de sandbox publicada por este repo, así que este endpoint sigue en la categoría `legacy-doc` para planeación de producción. Confianza por método [#confianza-por-método] | Método | Confianza | Motivo | | ------------------------------------ | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `pse` | más alta | varias fuentes coinciden en `bank` y en la dependencia de `GET /get_banks/1/` | | `NEQUI` | media | la forma del request es consistente entre Spotlight y el research posterior, pero el runtime sigue variando según los datos del pagador | | `daviplata` | media | Spotlight y el research posterior documentan el paso de OTP, pero Cobru no ha publicado todavía una repetición completa confirmada en este repo | | `credit_card` | media | Spotlight trae un payload claro y tarjetas de prueba, pero la paridad productiva aún requiere revalidación | | `breb` | media-baja | Spotlight documenta `payment: "breb"` directo, pero el research posterior en sandbox lo observó como deshabilitado o restringido comercialmente | | métodos en efectivo y corresponsales | media-baja | los payloads están documentados, pero el detalle de las respuestas sigue viniendo sobre todo de material legacy | Propósito [#propósito] Después de crear un cobru, este endpoint recibe los datos del pagador y los campos requeridos por el método de pago seleccionado. Este es el hub de checkout para: * Bre-B * PSE * Efecty y Corresponsal Bancolombia * Nequi * dale! * Botón Bancolombia * Daviplata * tarjetas de crédito Parámetro de path [#parámetro-de-path] | Campo | Tipo | Descripción | | ----- | ------ | ------------------------------------------- | | `url` | string | slug del cobru retornado por `POST /cobru/` | Campos comunes [#campos-comunes] ```json { "name": "Juan Perez", "payment": "efecty", "cc": "1140867070", "email": "juan@cobru.co", "document_type": "CC", "phone": "3002794981" } ``` | Campo | Requerido | Notas | | --------------- | --------------------------- | ----------------------------------------------- | | `name` | sí en la mayoría de métodos | nombre del pagador | | `payment` | sí | selector del método de pago | | `cc` | sí en la mayoría de métodos | número de documento del pagador | | `email` | sí en la mayoría de métodos | email del pagador | | `document_type` | sí en la mayoría de métodos | Spotlight muestra `CC`, `TI`, `CE`, `NIT`, `PA` | | `phone` | sí en la mayoría de métodos | teléfono del pagador | Usa el campo `payment`, no `payment_method`. Spotlight y el research posterior apuntan a `payment` como el selector aceptado. Respuestas y errores observados en Spotlight [#respuestas-y-errores-observados-en-spotlight] | Status | Causa | Notas | | ------ | -------------------------------------------------- | ------------------------------------------------------------------- | | `200` | detalles de pago generados | la forma de la respuesta cambia según el método | | `403` | intentas pagar tu propio cobru con saldo Cobru | Spotlight muestra `{"result":"same_user"}` | | `400` | el dueño superaría su balance permitido | `{"result":"LIMIT_BALANCE"}` | | `400` | el cobru ya fue pagado | `{"result":"COBRU_IS_PAYED"}` | | `400` | método de pago desconocido | `{"error": true, "msg": "unknown payment method"}` | | `400` | método no habilitado | `{"error":"Payment method is not enabled.","result":"NOT_ALLOWED"}` | | `404` | no se encontró el usuario que paga con saldo Cobru | solo flujo legacy | Matriz de métodos [#matriz-de-métodos] | Método | literal de `payment` | Campos extra | Siguiente paso | | ------------------------ | -------------------------- | ----------------------------------------------- | --------------------------------------------------- | | Bre-B | `breb` | ninguno en el request base | mostrar `qr_value` / `key_value` | | PSE | `pse` | `bank`, `address` | redirigir a la URL PSE retornada por Cobru | | Efecty | `efecty` | ninguno además de los comunes | mostrar los detalles de pago en efectivo retornados | | Corresponsal Bancolombia | `corresponsal_bancolombia` | ninguno además de los comunes | mostrar los detalles de pago retornados | | Nequi | `NEQUI` | `phone_nequi`, `push` opcional | usar `checkout` o respuesta tipo QR | | dale! | `dale` | ninguno además de los comunes | seguir la respuesta retornada por Cobru | | Botón Bancolombia | `bancolombia_transfer` | ninguno además de los comunes | redirigir a `checkout` | | Daviplata | `daviplata` | ninguno en el primer request | confirmar luego con OTP | | Tarjeta de crédito | `credit_card` | `credit_card`, `expiration_date`, `cvv`, `dues` | completar el flujo de tarjeta | Bre-B [#bre-b] ```json { "payment": "breb" } ``` Spotlight muestra una respuesta que incluye: * `qr_value` * `key_value` * `method: "breb"` * `franchise: "breb"` Los materiales originales también indican que `qr_value` y `key_value` viven 5 minutos. El research posterior en sandbox observó `payment: "breb"` directo como deshabilitado o restringido comercialmente en algunos entornos. Toma la forma del request como documentada, pero no asumas disponibilidad directa de Bre-B sin tu propia confirmación en sandbox. PSE [#pse] PSE requiere dos campos extra: | Campo | Tipo | Descripción | | --------- | ------ | ------------------------- | | `bank` | string | código numérico del banco | | `address` | string | dirección del pagador | ```json { "name": "Juan Perez", "payment": "pse", "cc": "1140867070", "email": "juan@cobru.co", "document_type": "CC", "phone": "300000000", "bank": "1040", "address": "Bogotá, Colombia" } ``` Antes de enviar `payment: "pse"`, consulta `GET /get_banks/1/` y envía en `bank` el `bankCode` elegido. Dentro de las variantes legacy de checkout, PSE es una de las mejor corroboradas en los materiales de Cobru porque la dependencia de bancos, los campos del request y el patrón de redirección coinciden entre varias fuentes. Si el request es exitoso, Cobru retorna la URL de PSE a la que tu frontend debe redirigir al usuario. Métodos en efectivo: Efecty y Corresponsal Bancolombia [#métodos-en-efectivo-efecty-y-corresponsal-bancolombia] Spotlight agrupa estos métodos como generación de detalles de pago en efectivo. ```json { "name": "Juan Perez", "payment": "efecty", "cc": "1140867070", "email": "juan@cobru.co", "document_type": "CC", "phone": "3002794981" } ``` `corresponsal_bancolombia` usa la misma forma base, cambiando solo el literal `payment`. Nequi [#nequi] ```json { "name": "Test Gómez", "payment": "NEQUI", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC", "phone_nequi": "307654332", "push": true } ``` Comportamiento descrito por Spotlight: * `push: true` genera un push en la app Nequi del usuario * `push: false` evita el push y retorna la data necesaria para una experiencia tipo QR, incluyendo `ref` dale! [#dale] ```json { "name": "Test Gómez", "payment": "dale", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC" } ``` Botón Bancolombia [#botón-bancolombia] ```json { "name": "Test Gómez", "payment": "bancolombia_transfer", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC" } ``` Spotlight indica que la respuesta incluye un `checkout` URL que el usuario debe abrir para completar el pago. Daviplata [#daviplata] Request inicial: ```json { "name": "Test Gómez", "payment": "daviplata", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC" } ``` Después de que el pagador recibe el OTP de Daviplata, Spotlight requiere una segunda llamada: `POST /cobru/confirm_daviplata/` Campos del body: | Campo | Descripción | | ----- | --------------------------- | | `URL` | URL/slug del cobru | | `OTP` | OTP recibido por el pagador | El éxito se describe como `result == "OK"`. Cobru todavía no ha publicado una repetición completa del OTP de Daviplata dentro de la evidencia de sandbox de este repo. Usa este contrato como una referencia legacy fuerte, no como un flujo verificado recientemente. Tarjeta de crédito [#tarjeta-de-crédito] ```json { "name": "Test Gómez", "payment": "credit_card", "cc": "1082626262", "email": "test@cobru.co", "phone": "307654332", "document_type": "CC", "credit_card": "4111111111111111", "expiration_date": "12/30", "cvv": "123", "dues": 1 } ``` Spotlight indica: * Cobru no persiste los datos de tarjeta * en producción el tráfico debe ser HTTPS * tarjetas de prueba mostradas en Spotlight: * aprobada: `4111 1111 1111 1111` * rechazada: `4111 1111 1111 1112` Páginas relacionadas [#páginas-relacionadas] * [Flujo de pago Bre-B](/es/docs/guides/qr-breb) * [Bre-B](/es/docs/api/cobrus/breb) * [Pagos PSE](/es/docs/api/cobrus/pse) * [Pagos en efectivo](/es/docs/api/cobrus/cash-payments) * [Nequi](/es/docs/api/cobrus/nequi) * [Daviplata](/es/docs/api/cobrus/daviplata) --- # Códigos de bancos PSE Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/pse-banks Endpoint [#endpoint] `GET /get_banks/1/` Este endpoint aparece en materiales legacy de Cobru y es una dependencia común cuando se presenta un selector de bancos PSE al usuario. Ejemplo de respuesta [#ejemplo-de-respuesta] ```json [ { "bankName": "BANCO AGRARIO", "bankCode": "1040" }, { "bankName": "BANCO AV VILLAS", "bankCode": "1052" }, { "bankName": "BANCO BBVA COLOMBIA S.A.", "bankCode": "1013" } ] ``` --- # Pagos PSE Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/pse Endpoint [#endpoint] `POST /{url}` Dependencia obligatoria [#dependencia-obligatoria] Antes de llamar el endpoint de detalles de pago con PSE, consulta el catálogo de bancos en: `GET /get_banks/1/` Usa el `bankCode` seleccionado dentro del campo `bank`. PSE es una de las variantes legacy de checkout mejor corroboradas dentro de los materiales de Cobru. La dependencia de bancos, la forma del request y el patrón de redirección coinciden entre Spotlight, notas compiladas de API y research posterior. Request [#request] ```json { "name": "Juan Perez", "payment": "pse", "cc": "1140867070", "email": "juan@cobru.co", "document_type": "CC", "phone": "300000000", "bank": "1040", "address": "Bogotá, Colombia" } ``` Siguiente paso [#siguiente-paso] Si el request es exitoso, Cobru retorna la URL de PSE a la que tu frontend debe redirigir al usuario. --- # Cotizar un cobru Locale: es URL: https://docs.cobru.co/es/docs/api/cobrus/quote Endpoint [#endpoint] `POST /cobru/estimate/` Documentado en materiales legacy de Cobru. Útil para previsualizaciones de carrito y estimación merchant-side. Ejemplo de request [#ejemplo-de-request] ```json { "amount": "5000", "client_assume_costs": true } ``` Ejemplo de response [#ejemplo-de-response] ```json { "cobru_amount": 5000, "cobru_fee": 295, "iva": 56.05, "cobru_payed_amount": 4700 } ``` --- # Envíos Locale: es URL: https://docs.cobru.co/es/docs/api/envios Esta familia está documentada a partir de materiales legacy de Cobru y capturas del menú del producto. Revalida paths, filtros y side effects del movimiento de saldo en sandbox antes de depender de ella en flujos críticos de producción. La superficie de transferencias aparece bajo `Envios` en el menú API de Cobru. Es la mejor forma documentada de mover saldo disponible entre usuarios Cobru sin abrir un flujo de retiro bancario. Cuándo usar envíos [#cuándo-usar-envíos] * mover saldo entre cuentas operadas dentro de Cobru * disparar flujos de soporte, operaciones o desembolsos wallet-to-wallet * construir una experiencia de transferencias internas antes de usar rieles bancarios Autenticación [#autenticación] Los envíos están documentados como operaciones autenticadas del usuario. Trátalos como endpoints sensibles al saldo y exige una sesión o token válido antes de llamarlos. Endpoints [#endpoints] | Endpoint | Método | Path | Estado | | ---------------------------- | ------ | -------- | -------------------------------- | | enviar dinero a otro usuario | `POST` | `/send/` | documentado en materiales legacy | | obtener envíos del usuario | `GET` | `/send/` | documentado en materiales legacy | Ciclo de vida del envío [#ciclo-de-vida-del-envío] Confirma que la cuenta emisora esté completamente habilitada. Los materiales legacy de Cobru indican que el emisor debe tener email y teléfono verificados antes de enviar saldo. Envía saldo a otro usuario Cobru usando el número de teléfono del destinatario como el identificador mejor documentado. Reconcilia el historial de envíos desde el endpoint de listado antes de mostrar un estado final en un dashboard o panel operativo. Restricciones conocidas [#restricciones-conocidas] * La identidad del destinatario está documentada como un identificador basado en teléfono. * Los materiales públicos todavía no confirman idempotencia, paginación ni campos explícitos de estado. * Si tu flujo necesita liquidación bancaria, usa retiros a bancos en lugar de `Envios`. --- # Obtener envíos Locale: es URL: https://docs.cobru.co/es/docs/api/envios/list Este endpoint está documentado a partir de materiales legacy de Cobru, pero filtros y paginación todavía necesitan verificación fresca desde un ambiente real. Endpoint [#endpoint] `GET /send/` Campos vistos en materiales legacy [#campos-vistos-en-materiales-legacy] | Field | Tipo | Notas | | ----------- | -------- | --------------------------------------------------- | | `from_user` | `string` | Identificador del emisor. | | `to_user` | `string` | Identificador del destinatario. | | `amount` | `number` | Monto del envío. | | `date` | `string` | Timestamp de creación o fecha formateada del envío. | Cómo usar el listado [#cómo-usar-el-listado] * reconciliar envíos salientes en un panel operativo * confirmar si una solicitud de envío ya fue registrada * construir tooling de soporte para movimientos wallet-to-wallet Lo que todavía falta confirmar [#lo-que-todavía-falta-confirmar] * campos de paginación * filtros disponibles * si el listado incluye un estado explícito o solo el registro base del movimiento --- # Enviar dinero Locale: es URL: https://docs.cobru.co/es/docs/api/envios/send Este contrato proviene de materiales legacy de Cobru. Revalida request y response exactos en sandbox antes de usarlo en un flujo de transferencias de producción. Endpoint [#endpoint] `POST /send/` Requisitos [#requisitos] * el emisor debe tener email y teléfono verificados * el destinatario se identifica por número de teléfono Campos del request [#campos-del-request] | Field | Tipo | Requerido | Notas | | --------- | -------- | --------- | ---------------------------------------------------------------------------------------------------------------- | | `to_user` | `string` | sí | Mejor identificador conocido del destinatario. Los materiales legacy lo describen como el teléfono del receptor. | | `amount` | `number` | sí | Monto a enviar desde el saldo disponible del usuario autenticado. | En algunos textos antiguos aparece `toUser` en camelCase. Prefiere `to_user` salvo que Cobru confirme un alias adicional aceptado. Ejemplo de body [#ejemplo-de-body] ```json { "amount": 99000, "to_user": "3001234567" } ``` Notas de producción [#notas-de-producción] * Valida KYC y estado operativo del emisor antes de exponer esta acción en UI. * Los materiales públicos no confirman si el envío es síncrono, en cola o reversible. * Trata el éxito del envío como no confiable hasta reconciliarlo vía `GET /send/` o con tu propio ledger downstream. --- # Referencia API Locale: es URL: https://docs.cobru.co/es/docs/api/reference --- # Recarga celular Locale: es URL: https://docs.cobru.co/es/docs/api/services/cell-recharge Este flujo de recarga está documentado desde exports legacy de Cobru. Los operadores soportados y el payload de respuesta todavía deben validarse antes de usarlo en producción. Endpoint [#endpoint] `POST /request_service_reload/` Campos del request vistos en documentación legacy [#campos-del-request-vistos-en-documentación-legacy] | Field | Tipo | Requerido | Notas | | ----------- | -------- | --------- | ------------------------------------------------------ | | `value` | `number` | sí | Monto de la recarga. | | `recipient` | `string` | sí | Número de teléfono destino. | | `operator` | `string` | sí | Código o nombre del operador móvil esperado por Cobru. | Campos de respuesta vistos en documentación antigua [#campos-de-respuesta-vistos-en-documentación-antigua] | Field | Tipo | Notas | | --------- | -------- | --------------------------------- | | `result` | `string` | Resultado de la recarga. | | `message` | `string` | Mensaje del proveedor o de Cobru. | Operadores vistos en materiales legacy [#operadores-vistos-en-materiales-legacy] Los exports antiguos mencionan operadores como `claro`, `movistar`, `tigo` y `avantel`. Trata esa lista como indicativa hasta confirmar el catálogo vivo actual. --- # Servicios digitales Locale: es URL: https://docs.cobru.co/es/docs/api/services La familia de servicios está documentada desde exports legacy de Cobru y visibilidad en el menú del producto. La capacidad general es clara, pero debes validar comportamiento de inventario y payloads de fulfillment antes de salir a producción. El menú API de Cobru expone una sección `Servicios` para productos digitales. Estos endpoints son útiles cuando Cobru funciona como superficie de distribución de bienes digitales además de API de pagos. Elige un workflow de servicios [#elige-un-workflow-de-servicios] Capacidades visibles [#capacidades-visibles] | Capacidad | Método | Path | Confianza | | -------------------------- | ------ | -------------------------- | ---------- | | recarga celular | `POST` | `/request_service_reload/` | legacy-doc | | lista de productos PIN | `GET` | `/pines/all_pines/` | legacy-doc | | compra de PINes | `POST` | `/pin/` | legacy-doc | | lista de paquetes de datos | `GET` | `/packages/all_packages/` | legacy-doc | | compra de paquetes | `POST` | `/packages/buy/` | legacy-doc | Flujo de servicio [#flujo-de-servicio] Consulta primero catálogo u operadores antes de mostrar una oferta al usuario final. Crea la recarga, compra de PIN o compra de paquete con los campos esperados por el proveedor. Reconcilia el resultado del fulfillment y la disponibilidad de inventario antes de confirmar éxito al cliente. --- # Comprar PINes Locale: es URL: https://docs.cobru.co/es/docs/api/services/pins-buy Este flujo de compra está documentado desde exports legacy de Cobru. Confirma reglas de inventario y payload final de fulfillment antes de usarlo en producción. Endpoint [#endpoint] `POST /pin/` Campos del request vistos en documentación legacy [#campos-del-request-vistos-en-documentación-legacy] | Field | Tipo | Requerido | Notas | | ---------- | -------- | --------- | ---------------------------------------------- | | `id_pin` | `number` | sí | Identificador del producto PIN en el catálogo. | | `operator` | `string` | sí | Identificador del proveedor u operador. | Campos de respuesta vistos en documentación antigua [#campos-de-respuesta-vistos-en-documentación-antigua] | Field | Tipo | Notas | | -------- | -------- | ------------------------------------ | | `status` | `string` | Resultado de la compra. | | `pin` | `string` | PIN o código de redención entregado. | | `pk` | `number` | Identificador de la compra en Cobru. | --- # Lista de PINes Locale: es URL: https://docs.cobru.co/es/docs/api/services/pins-list Este endpoint de catálogo está documentado desde exports legacy de Cobru. Verifica filtros y schema del catálogo en un ambiente real antes de depender de él. Endpoint [#endpoint] `GET /pines/all_pines/` Variante opcional de query vista en docs antiguas [#variante-opcional-de-query-vista-en-docs-antiguas] `GET /pines/all_pines/?operator={operator}` Usa la variante filtrada por operador cuando quieras prefiltrar el catálogo de PINes para un proveedor específico. --- # Tokenización Locale: es URL: https://docs.cobru.co/es/docs/api/tokenization Esta superficie viene de materiales legacy de Cobru y todavía necesita una validación fresca en sandbox. Trátala como contrato beta hasta contar con el export oficial de OpenAPI o una nueva verificación endpoint por endpoint. Para qué sirve esta capability [#para-qué-sirve-esta-capability] Usa tokenización cuando tu integración necesite: * registrar una tarjeta una sola vez y cobrarla después * evitar recolectar PAN completo en cada flujo de pago * listar tarjetas guardadas de la cuenta autenticada * eliminar tarjetas almacenadas cuando el usuario lo solicite Flujo Cobru [#flujo-cobru] Obtén la llave pública RSA desde `GET /base/get_constants_key_public/`. Encripta los campos sensibles de la tarjeta en el cliente o en un servicio con alcance PCI. Registra la tarjeta con `POST /register_tc/`. Consulta tarjetas con `GET /list_tc/` y cobra con `POST /tc_payment/`. Mapa de endpoints [#mapa-de-endpoints] | Endpoint | Propósito | Estado | | ------------------------------------- | --------------------------------------------------------- | ---------- | | `GET /base/get_constants_key_public/` | Obtener la llave pública RSA | Legacy doc | | `POST /register_tc/` | Registrar un token de tarjeta | Legacy doc | | `GET /list_tc/` | Listar tarjetas guardadas o consultar una por `card_uuid` | Legacy doc | | `POST /tc_payment/` | Pagar con una tarjeta guardada o tokenizada | Legacy doc | | `DELETE /delete_tc/` | Eliminar una tarjeta almacenada | Legacy doc | Modelo de autenticación [#modelo-de-autenticación] Los exports de Spotlight sugieren que los endpoints de tokenización son superficies autenticadas del usuario. Hasta completar una nueva validación en sandbox, asume que: * aplican los headers estándar de autenticación Cobru * las requests deben salir de un backend confiable o de servicios con alcance PCI * `x-api-key` nunca debe vivir en frontend público Ejemplo: obtener la llave pública [#ejemplo-obtener-la-llave-pública] ```bash curl -X GET https://dev.cobru.co/base/get_constants_key_public/ \ -H "x-api-key: $COBRU_API_KEY" \ -H "Authorization: Bearer $COBRU_ACCESS_TOKEN" ``` ```ts const response = await fetch('https://dev.cobru.co/base/get_constants_key_public/', { method: 'GET', headers: { 'x-api-key': process.env.COBRU_API_KEY!, Authorization: `Bearer ${accessToken}`, }, }); const payload = await response.json(); console.log(payload.data.text_long_value); ``` ```python import requests response = requests.get( "https://dev.cobru.co/base/get_constants_key_public/", headers={ "x-api-key": COBRU_API_KEY, "Authorization": f"Bearer {access_token}", }, ) print(response.json()) ``` ```php request('GET', 'https://dev.cobru.co/base/get_constants_key_public/', [ 'headers' => [ 'x-api-key' => getenv('COBRU_API_KEY'), 'Authorization' => 'Bearer ' . $accessToken, ], ]); $payload = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR); var_dump($payload); ``` Notas operativas [#notas-operativas] El flujo legacy de Cobru espera encriptación RSA para número de tarjeta, nombre del titular y fecha de expiración. Incluso con tokenización, debes tratar la captura y el transporte como sensibles a PCI hasta que Cobru publique un modelo de confianza más acotado. La documentación legacy menciona campos móviles/dispositivo como `imei`, `latitude` y `longitude`. No los asumas como universalmente obligatorios hasta confirmar el contrato actual. Usa tokenización de Cobru solo desde backend o desde un proxy con alcance PCI, registra únicamente identificadores enmascarados y diseña tu propio flujo de recuperación para eliminación de tarjetas. Siguientes pasos [#siguientes-pasos] Explora los métodos de tokenización dentro de la referencia OpenAPI interactiva. Continúa con las tarjetas emitidas por Cobru y sus operaciones posteriores.