Skip to main content

Payments API

Process payments and manage transactions using MercadoPago integration.

Create Payment

Endpoint: POST /create-payment Authentication: Not required (public endpoint) Creates a payment and returns a MercadoPago checkout link.

Request Body

amount
number
Total amount to charge (mutually exclusive with originalAmount)
originalAmount
number
Base amount before surcharges (mutually exclusive with amount)
appointmentId
string
required
Associated appointment/booking ID
description
string
Payment description (default: “Consulta Legal”)
userId
string
Client user ID (“guest” for anonymous users)
lawyerId
string
Lawyer user ID (“consulta-general” for general consultations)
successUrl
string
Redirect URL on successful payment
failureUrl
string
Redirect URL on failed payment
pendingUrl
string
Redirect URL for pending payment
userEmail
string
Client email address
userName
string
Client name

Payment Calculation

The system automatically calculates:
  • Original Amount: Base price set by lawyer
  • Client Surcharge: Platform fee paid by client (default 10%)
  • Platform Fee: Commission kept by platform (default 20% of original)
  • Lawyer Amount: Amount transferred to lawyer (80% of original)
These percentages are configurable in platform_settings table.

Example Request

{
  "originalAmount": 30000,
  "appointmentId": "abc123def-4567-89ab-cdef-0123456789ab",
  "description": "Consulta Derecho Civil - 1 hora",
  "userId": "guest",
  "lawyerId": "550e8400-e29b-41d4-a716-446655440000",
  "userEmail": "[email protected]",
  "userName": "Carlos Rodríguez",
  "successUrl": "https://legalup.cl/payment/success",
  "failureUrl": "https://legalup.cl/payment/failure",
  "pendingUrl": "https://legalup.cl/payment/pending"
}

Response

success
boolean
Operation success status
payment_id
string
Created payment ID (UUID)
MercadoPago checkout URL
message
string
Success message

Example Response

200 - Success
{
  "success": true,
  "payment_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "payment_link": "https://www.mercadopago.cl/checkout/v1/redirect?pref_id=123456789-abc123",
  "message": "Payment created successfully"
}

Error Responses

400 - Missing Fields
{
  "error": "Missing required fields",
  "required": ["amount or originalAmount", "appointmentId"],
  "received": {
    "amount": null,
    "originalAmount": null,
    "appointmentId": "abc123"
  }
}
400 - Invalid Amount
{
  "error": "Amount must be at least 1000 CLP"
}
500 - Server Error
{
  "error": "Internal server error",
  "details": "MercadoPago API Error: ..."
}

Get Payment Status

Endpoint: GET /payment/:paymentId Authentication: Not required

Path Parameters

paymentId
string
required
Payment ID (UUID)

Response

payment
object
Payment details
id
string
Payment ID
original_amount
number
Base amount (CLP)
client_surcharge
number
Surcharge amount (CLP)
client_surcharge_percent
number
Surcharge percentage (e.g., 0.1 for 10%)
platform_fee
number
Platform commission (CLP)
platform_fee_percent
number
Platform fee percentage (e.g., 0.2 for 20%)
lawyer_amount
number
Amount for lawyer (CLP)
currency
string
Currency code (“CLP”)
status
string
Payment status: pending, succeeded, failed
user_id
string
Client user ID
lawyer_id
string
Lawyer user ID
metadata
object
Additional payment metadata
description
string
Payment description
appointment_id
string
Associated appointment ID
client_total
number
Total amount paid by client (including surcharge)
payment_gateway_id
string | null
MercadoPago payment ID
created_at
string
Creation timestamp (ISO 8601)
updated_at
string
Last update timestamp (ISO 8601)

Example Response

200 - Success
{
  "payment": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "original_amount": 30000,
    "client_surcharge": 3000,
    "client_surcharge_percent": 0.1,
    "platform_fee": 6000,
    "platform_fee_percent": 0.2,
    "lawyer_amount": 24000,
    "currency": "CLP",
    "status": "succeeded",
    "user_id": "abc123-user-id",
    "lawyer_id": "def456-lawyer-id",
    "metadata": {
      "description": "Consulta Derecho Civil",
      "appointment_id": "xyz789-appointment-id",
      "client_total": 33000,
      "payment_gateway_id": "1234567890"
    },
    "created_at": "2026-03-04T10:00:00.000Z",
    "updated_at": "2026-03-04T10:05:00.000Z"
  }
}
404 - Not Found
{
  "error": "Payment not found"
}

MercadoPago Webhook

Endpoint: POST /api/mercadopago/webhook Authentication: MercadoPago signature validation Receives payment notifications from MercadoPago.
This endpoint is called automatically by MercadoPago. Do not call it directly.

Webhook Payload

type
string
Notification type (“payment”)
topic
string
Event topic (“payment”)
data
object
Event data
id
string
MercadoPago payment ID

Example Webhook Payload

{
  "type": "payment",
  "topic": "payment",
  "data": {
    "id": "1234567890"
  }
}

Webhook Actions (Approved Payment)

When a payment is approved, the system:
  1. Updates booking status to confirmed
  2. Creates user account if guest booking
  3. Creates/updates profile for the user
  4. Creates appointment record for lawyer dashboard
  5. Associates booking with user
  6. Sends email confirmations to client and lawyer
  7. Tracks payment event for analytics

Response

200 - OK
OK
500 - Error
{
  "error": "Internal server error"
}

Manual Payment Reconciliation

Endpoint: POST /api/mercadopago/reconcile/:paymentId Authentication: Secret header required Use case: Backup endpoint if webhook delivery fails

Headers

x-reconcile-secret
string
required
Admin reconciliation secret (env: MP_RECONCILE_SECRET)

Path Parameters

paymentId
string
required
MercadoPago payment ID (not upLegal payment ID)

Response

success
boolean
Reconciliation success
paymentId
string
MercadoPago payment ID
external_reference
string
Booking/appointment ID
bookingUpdated
boolean
Whether booking was updated
clientUserId
string
Created or found client user ID

Example Response

200 - Success
{
  "success": true,
  "paymentId": "1234567890",
  "external_reference": "abc123-booking-id",
  "bookingUpdated": true,
  "clientUserId": "def456-user-id"
}
401 - Unauthorized
{
  "error": "Unauthorized"
}
404 - Not Found
{
  "error": "Payment not found"
}
409 - Not Approved
{
  "error": "Payment not approved",
  "status": "pending",
  "status_detail": "pending_waiting_payment",
  "external_reference": "abc123-booking-id"
}

Payment States

StatusDescription
pendingPayment created, awaiting confirmation
succeededPayment successful, funds transferred
failedPayment failed or rejected

Currency

All payments are processed in Chilean Pesos (CLP). The minimum payment amount is 1,000 CLP.

RLS Policies

Payments Table

  • SELECT: Users can view their own payments (as client or lawyer)
  • INSERT: Service role only (via RPC function)
  • UPDATE: Service role only (via webhook)
  • DELETE: Not allowed

Test Mode

MercadoPago sandbox credentials can be used for testing:
  • Test cards available at MercadoPago Developers
  • Sandbox payments return sandbox_init_point instead of init_point

Build docs developers (and LLMs) love