TuCOPRamp

Pay from your own payments provider account

Pay Bre-B keys with your API key alone, from your account with the payments provider that TuCOP linked to your integrator.

Pick your integration model before you build. There are two:

ModelWho goes through identity verificationWhat each request carries
Per user (most integrators)Each of your users, as a partyYour API key and the user's party session
Your own payments provider accountYour business, once, set up with TuCOPYour API key alone

Most integrators pay for their users: each user signs in with a party session and goes through identity verification. Some integrators pay instead from one account of their own with TuCOP's payments provider, as a business. For them, TuCOP links that account to the integrator. After that, the pay endpoints take your API key alone, with no party session, and act for the party that holds that account. The rest of this page is about that second model.

How it is set up

  1. Ask TuCOP

    Write to support@tucop.org. TuCOP needs your integrator to have the pay product (and deposit, if you want a deposit account).

  2. TuCOP links the account

    A TuCOP operator links your payments provider account to your integrator in the admin. This is done once per environment: the sandbox and production are linked separately.

  3. Check it

    GET /parties/me with the key alone returns the party that holds the account and its status. It can pay once status.kyc is approved, status.tos is accepted, the cop endorsement is approved and restricted is false.

Which endpoints take the key alone

EndpointKey alone
/destinations (all methods)Yes. Third-party keys only: a first_party key answers 409 first_party_not_available.
POST /quotes with product: "pay"Yes
POST /payments, GET /payments/{id}, POST /payments/{id}/cancelYes
GET /limitsYes
GET /ratesYes. It always takes the key alone, for every integrator.
/deposits (all methods)Yes. Production only.
POST /withdrawals, POST /quotes with product: "withdraw"Only when the party that holds your account has an identity document. The party TuCOP creates when it links your account has none, so these answer 409 first_party_not_available.
GET /withdrawals, GET /withdrawals/{id}, DELETE /withdrawals/{id}Yes. Without an address, the list is empty and the others answer 404 withdrawal_not_found. DELETE also needs the withdraw product.
GET /parties/meYes
POST /partiesNo. It always needs a party session.

Send the key in X-TuCOPRamp-Key or Authorization: Bearer, and an Idempotency-Key on every POST and PATCH, as on any platform endpoint. Do not send X-TuCOPRamp-Party-Session.

If you do send a party session, TuCOP uses it as usual. On a quote, a payment or a new third-party destination, a session for a party other than the one that holds your account gets 403 integrator_customer_mismatch: your integrator pays only from its own account.

Pay a Bre-B key, end to end

  1. Register the destination

    bash
    curl https://api.ramp.tucop.xyz/destinations \
      --request POST \
      --header "X-TuCOPRamp-Key: $TUCOPRAMP_API_KEY" \
      --header "Idempotency-Key: 5f0c7a1e-3b8d-4f42-9a6e-1c2d3e4f5a6b" \
      --header "Content-Type: application/json" \
      --data '{ "ownership": "third_party", "bre_b_key": "3001234567", "owner_name": "Carlos Ruiz" }'
    

    The answer is 202 with status: "pending", or 200 with the existing destination when you already registered this key. owner_name is optional: without it the key is looked up and the directory's holder comes back in holder.

  2. Wait until it is verified

    Listen for destination.verified or destination.rejected, or poll GET /destinations/{id} every few seconds. The Bre-B directory answers in about a minute. Only a verified destination can be paid. See Destinations.

  3. Confirm the holder

    Check holder.name, holder.bank and holder.document_last4 against the account you mean to pay, then POST /destinations/{id}/confirm. Without it the payment gets 409 destination_not_confirmed.

  4. Quote

    Optionally, first GET /rates?amount_cop=150000 to show an estimate of the USDC it takes; see Estimate before you quote. It is not binding. Then POST /quotes with product: "pay", the destination_id and amount_cop in whole pesos. The quote lasts 2 minutes and pays once.

  5. Create the payment

    POST /payments with quote_id and return_address. return_address is required here: there is no wallet session to default to, so without it the answer is 422 return_address_required. It is the wallet the USDC is sent from, and where the provider returns it if the payout fails.

    bash
    curl https://api.ramp.tucop.xyz/payments \
      --request POST \
      --header "X-TuCOPRamp-Key: $TUCOPRAMP_API_KEY" \
      --header "Idempotency-Key: 3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f" \
      --header "Content-Type: application/json" \
      --data '{
        "quote_id": "qte_01j9z3k9a1b2c3d4e5f6g7h8j9",
        "return_address": "0x1111111111111111111111111111111111111111"
      }'
    
  6. Send the USDC

    Send exactly deposit.amount of USDC on Celo to deposit.address, from return_address.

  7. Follow

    Listen for operation.updated, or poll GET /payments/{id}, until status is completed, failed, refunded or canceled. After the USDC land on-chain, the pesos usually reach the Bre-B key within 15 to 30 minutes (settlement_time on the payment); meanwhile the payment reads awaiting_funds while the provider detects the deposit, then processing. Neither is a failure. See Payments.

Deposit account

POST /deposits with the key alone gives the party a reusable Bre-B key: pesos paid there arrive as USDC on Celo. Send wallet_address, the wallet the USDC goes to; without it the answer is 422 wallet_address_required. Deposit accounts work only in production. See Deposits.

If your payments provider account already has an active deposit account for that wallet, opened outside TuCOP, POST /deposits takes it over instead of opening another one: it answers 200 with that account's Bre-B key and its own fee in fee_bps. So a fixed Bre-B key you already give your buyers keeps working, now with deposit.received webhooks. See An account the provider already has.

To send the USDC of that same key to another wallet, use PATCH /deposits/{id} with wallet_address, also with the key alone. TuCOP makes the change with your payments provider key, so that key must be allowed to update deposit accounts at the provider; until it is, the answer is 502 provider_unavailable and nothing changes. See Change the wallet.

Limits and fees

  • Limits are your integrator's, the same as for any integrator: 200,000 COP minimum per payment and 100,000,000 COP per calendar month, unless TuCOP set other values for you. GET /limits shows them and what is used. See Payments.
  • TuCOP's fee is set by TuCOP for each integrator. The quote shows it in fees.tucop.
  • Your own fee (fees.consumer) is not part of the deposit. Charge it yourself if you use one.

Errors

CodeStatusWhen
party_session_required401No session was sent, and TuCOP has not linked a payments provider account to your integrator. Also POST /parties with the key alone.
integrator_customer_mismatch403A session for another party on a quote, a payment or a new third-party destination.
product_not_enabled403Your integrator does not have the product.
party_restricted403TuCOP restricted the party that holds your account.
integrator_not_linked409TuCOP set a payments provider account for your integrator, but it is not linked yet. Contact TuCOP.
party_not_verified409The account holder's identity check, terms or COP endorsement is not approved.
first_party_not_available409A first_party destination, a withdraw quote or POST /withdrawals. This party stands for a payments provider account linked by TuCOP and has no identity document to match a first-party key. Use pay for third-party keys.
return_address_required422A payment without return_address.
wallet_address_required422A deposit account without wallet_address.

The rest are the same as on Destinations, Payments and Deposits.

Do not

  • Do not send X-TuCOPRamp-Party-Session on these calls, unless you mean to act for a different party through its own session.
  • Do not reuse a quote. Each quote pays once and lasts 2 minutes; ask for a new one.
  • Do not send more or less than deposit.amount, and do not send it from a wallet other than return_address.
  • Do not retry a 4xx unchanged. Fix the request and use a new Idempotency-Key.
  • Do retry a 5xx with the same Idempotency-Key. TuCOP carries on with the same payment and never creates a second payout.
  • Do not pay a destination you have not checked. Confirm the holder only after you compared it with the account you mean to pay.