When I first tried integrating MercadoPago with an AI-powered invoicing system for a Buenos Aires-based client last quarter, I hit a wall that cost me three hours: ConnectionError: Connection timeout after 30000ms while trying to verify a user's payment preference through the MercadoPago API. The issue? Argentina's strict data residency requirements mean MercadoPago's default sandbox endpoints don't route correctly through proxy configurations common in Latin American development environments. I eventually discovered that specifying the correct corp_type: 'AR' parameter alongside explicit region configuration resolved the issue entirely. This guide walks you through the complete setup process—saving you those three hours.
Why Argentine Developers Choose MercadoPago + AI APIs
MercadoPago dominates the Latin American payment landscape with over 45 million active users across Argentina, Brazil, Mexico, and Chile. For developers building AI-powered applications serving the LATAM market, combining MercadoPago's payment processing with intelligent API backends creates a robust monetization stack. Sign up here for HolySheep AI, which offers AI API access at rates starting at just $0.42 per million tokens for DeepSeek V3.2—that's 85%+ savings compared to typical ¥7.3 per 1K token pricing at other providers.
Key advantages for your integration:
- Local payment methods: Supports Argentina's PagoEfectivo, Rapipago, andProvincialnetworks
- Low processing fees: 5.99% + IVA for Argentine merchants (competitive vs 7.5%+ international processors)
- AI-ready infrastructure: MercadoPago webhooks integrate seamlessly with async AI processing pipelines
- Currency handling: Native ARS support without forced USD conversion
Prerequisites and Environment Setup
Before diving into code, ensure you have:
- Python 3.10+ (we'll use httpx for async HTTP calls)
- A MercadoPago Developer account with sandbox credentials
- Your HolySheep AI API key (available after registration)
- The
mercadopagoandhttpxpackages
Configuration: Environment Variables
Store your credentials securely in a .env file. Never hardcode sensitive values in your source code—I've seen production leaks cause real financial exposure.
# .env file for Argentine MercadoPago + HolySheep AI integration
MERCADO_PAGO_ACCESS_TOKEN=APP_USR-YourSandboxOrProductionTokenHere
MERCADO_PAGO_PUBLIC_KEY=APP_USR-YourPublicKeyHere
MERCADO_PAGO_USER_ID=YourMercadoPagoUserID
HolySheep AI Configuration
HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
HOLYSHEEP_BASE_URL=https://api.holysheep.ai/v1
Application Settings
APP_URL=https://yourapp.com
WEBHOOK_SECRET=your_webhook_signing_secret
COUNTRY=AR
CURRENCY=ARS
Core Integration: Payment Preference Creation
The foundation of any MercadoPago integration is creating payment preferences that specify what your customer is purchasing. Here's a complete implementation that handles Argentine-specific requirements including local payment methods and ARS currency:
import os
import httpx
import json
from typing import Optional
from dotenv import load_dotenv
load_dotenv()
class MercadoPagoClient:
"""Client for MercadoPago API with Argentine market optimizations."""
def __init__(self):
self.access_token = os.getenv("MERCADO_PAGO_ACCESS_TOKEN")
self.base_url = "https://api.mercadopago.com"
self.user_id = os.getenv("MERCADO_PAGO_USER_ID")
self.holysheep_api_key = os.getenv("HOLYSHEEP_API_KEY")
self.holysheep_base_url = os.getenv("HOLYSHEEP_BASE_URL")
async def create_payment_preference(
self,
items: list[dict],
payer_email: str,
external_reference: str,
metadata: Optional[dict] = None
) -> dict:
"""
Create a payment preference for Argentine market.
Args:
items: List of item dictionaries with 'title', 'quantity', 'currency_id', 'unit_price'
payer_email: Customer's email address
external_reference: Your internal order/transaction ID
metadata: Additional data to attach to the payment
Returns:
Preference object with 'init_point' (redirect URL) and 'id'
"""
preference_payload = {
"items": items,
"payer": {
"email": payer_email,
"identification": {
"type": "DNI", # Argentine national ID
"number": "" # Customer will fill this
}
},
"payment_methods": {
"excluded_payment_types": [
{"id": "credit_card"} # Exclude credit for specific use cases
],
"excluded_payment_methods": [
{"id": "amex"} # American Express not widely accepted in Argentina
],
"installments": 12 # Maximum installments for credit
},
"external_reference": external_reference,
"additional_info": {
"payer": {
"registration_date": None # Add if available
}
},
# CRITICAL for Argentina: Enable local payment methods
"binary_mode": False, # Allows partial payment processing
"statement_descriptor": "HOLYSHEEP AI SERVICES",
"campaign_id": None # Add MercadoPago campaign ID if running promotions
}
if metadata:
preference_payload["metadata"] = metadata
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(
f"{self.base_url}/checkout/preferences",
headers={
"Authorization": f"Bearer {self.access_token}",
"Content-Type": "application/json"
},
json=preference_payload
)
if response.status_code == 201:
return response.json()
else:
raise MercadoPagoError(
f"Failed to create preference: {response.status_code} - {response.text}"
)
async def verify_payment_with_ai(
self,
payment_id: str,
transaction_amount: float
) -> dict:
"""
Use HolySheep AI to analyze and verify payment legitimacy.
This is where you integrate AI capabilities with your payment flow.
"""
# First, fetch payment details from MercadoPago
async with httpx.AsyncClient(timeout=30.0) as client:
payment_response = await client.get(
f"{self.base_url}/v1/payments/{payment_id}",
headers={"Authorization": f"Bearer {self.access_token}"}
)
if payment_response.status_code != 200:
raise MercadoPagoError(f"Payment fetch failed: {payment_response.text}")
payment_data = payment_response.json()
# Now use HolySheep AI for payment analysis
analysis_prompt = f"""
Analyze this MercadoPago transaction for fraud indicators:
- Amount: {transaction_amount} ARS
- Payment Method: {payment_data.get('payment_type_id')}
- Status: {payment_data.get('status')}
- Card Last 4: {payment_data.get('card', {}).get('last_four_digits', 'N/A')}
- Customer Country: {payment_data.get('payer', {}).get('address', {}).get('city', 'Unknown')}
Provide a risk score 0-100 and recommendations.
"""
async with httpx.AsyncClient(timeout=45.0) as client:
ai_response = await client.post(
f"{self.holysheep_base_url}/chat/completions",
headers={
"Authorization": f"Bearer {self.holysheep_api_key}",
"Content-Type": "application/json"
},
json={
"model": "gpt-4.1",
"messages": [
{"role": "system", "content": "You are a fraud detection expert specializing in Latin American payment systems."},
{"role": "user", "content": analysis_prompt}
],
"max_tokens": 500,
"temperature": 0.3
}
)
if ai_response.status_code == 200:
return {
"payment": payment_data,
"ai_analysis": ai_response.json()["choices"][0]["message"]["content"]
}
else:
# Graceful degradation: return payment data without AI analysis
return {"payment": payment_data, "ai_analysis": None}
class MercadoPagoError(Exception):
"""Custom exception for MercadoPago API errors."""
pass
Usage example
async def main():
client = MercadoPagoClient()
# Create preference for AI API credits purchase
preference = await client.create_payment_preference(
items=[
{
"title": "HolySheep AI Credits - 100,000 Tokens",
"quantity": 1,
"currency_id": "ARS",
"unit_price": 15000.00 # Price in Argentine Pesos
}
],
payer_email="[email protected]",
external_reference="ORDER-12345"
)
print(f"Redirect customer to: {preference['init_point']}")
if __name__ == "__main__":
import asyncio
asyncio.run(main())
Webhook Handler: Processing Payment Notifications
MercadoPago sends webhook notifications when payment statuses change. Your handler must be production-ready with idempotency safeguards—duplicate webhook deliveries are common and can cause double-processing:
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse
import hmac
import hashlib
import json
import logging
from datetime import datetime
app = FastAPI()
logger = logging.getLogger(__name__)
In-memory idempotency cache (use Redis in production)
processed_webhooks = set()
WEBHOOK_EXPIRY_SECONDS = 3600
@app.post("/webhooks/mercadopago")
async def handle_mercadopago_webhook(request: Request):
"""
Process MercadoPago IPN (Instant Payment Notification) webhooks.
Important security measures:
1. Verify webhook signature
2. Implement idempotency
3. Handle all payment status transitions
"""
# Get raw body for signature verification
body = await request.body()
body_json = json.loads(body)
# Verify webhook authenticity
signature = request.headers.get("x-signature")
if not verify_webhook_signature(body, signature):
logger.warning("Invalid webhook signature received")
raise HTTPException(status_code=403, detail="Invalid signature")
topic = request.headers.get("x-topic", "payment")
resource_id = body_json.get("data", {}).get("id") or body_json.get("id")
if not resource_id:
raise HTTPException(status_code=400, detail="Missing resource ID")
# Idempotency check
webhook_key = f"{topic}:{resource_id}"
if webhook_key in processed_webhooks:
logger.info(f"Duplicate webhook ignored: {webhook_key}")
return JSONResponse(content={"status": "already_processed"})
try:
if topic == "payment":
await process_payment_webhook(resource_id)
elif topic == "merchant_order":
await process_merchant_order_webhook(resource_id)
else:
logger.warning(f"Unhandled webhook topic: {topic}")
# Mark as processed
processed_webhooks.add(webhook_key)
# Cleanup old entries (simplified—use Redis TTL in production)
if len(processed_webhooks) > 10000:
processed_webhooks.clear()
return JSONResponse(content={"status": "processed"})
except Exception as e:
logger.error(f"Webhook processing failed: {e}", exc_info=True)
# Return 200 to prevent MercadoPago retry storms for business logic errors
# Only return non-200 for signature/validation failures
return JSONResponse(
content={"status": "error", "message": str(e)},
status_code=500
)
def verify_webhook_signature(body: bytes, signature: str) -> bool:
"""
Verify the webhook signature using HMAC-SHA256.
MercadoPago sends signature in format: "t=timestamp,v1=signature"
"""
if not signature:
return False
webhook_secret = os.getenv("WEBHOOK_SECRET")
parts = dict(item.split("=") for item in signature.split(","))
timestamp = parts.get("t", "")
received_signature = parts.get("v1", "")
# Verify timestamp to prevent replay attacks (5-minute window)
current_time = int(datetime.now().timestamp())
if abs(current_time - int(timestamp)) > 300:
logger.warning("Webhook timestamp outside acceptable window")
return False
# Compute expected signature
payload = f"{timestamp}.{body.decode('utf-8')}"
expected_signature = hmac.new(
webhook_secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(received_signature, expected_signature)
async def process_payment_webhook(payment_id: str):
"""Handle payment status updates."""
# Fetch full payment details
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(
f"https://api.mercadopago.com/v1/payments/{payment_id}",
headers={"Authorization": f"Bearer {os.getenv('MERCADO_PAGO_ACCESS_TOKEN')}"}
)
payment = response.json()
status = payment.get("status")
external_ref = payment.get("external_reference")
logger.info(f"Processing payment {payment_id}, status: {status}, ref: {external_ref}")
if status == "approved":
# Fulfill the order—this is where you credit AI API usage
await fulfill_order(external_ref, payment)
elif status == "pending":
await handle_pending_payment(external_ref, payment)
elif status in ["cancelled", "rejected"]:
await handle_failed_payment(external_ref, payment)
async def fulfill_order(external_reference: str, payment_data: dict):
"""
Fulfill the customer's order after successful payment.
This would integrate with your database and HolySheep AI credit system.
"""
amount = payment_data.get("transaction_amount")
currency = payment_data.get("currency_id")
logger.info(f"Fulfilling order {external_reference}: {amount} {currency}")
# In production: Update your database, credit the user's account
# Example: await credit_user_account(external_reference, amount)
# Trigger AI-powered order confirmation email via HolySheep AI
await send_smart_confirmation(external_reference, payment_data)
async def send_smart_confirmation(order_ref: str, payment: dict):
"""Use HolySheep AI to generate personalized confirmation emails."""
prompt = f"""
Generate a confirmation email for a customer who just purchased AI API credits.
Order Reference: {order_ref}
Amount Paid: {payment.get('transaction_amount')} {payment.get('currency_id')}
Payment Method: {payment.get('payment_type_id')}
Date: {payment.get('date_approved')}
Include:
- Order summary
- How to use HolySheep AI API (include base URL: https://api.holysheep.ai/v1)
- Next steps for integration
- Customer support contact for Argentine market
Tone: Professional but friendly, in Spanish.
"""
async with httpx.AsyncClient(timeout=45.0) as client:
response = await client.post(
"https://api.holysheep.ai/v1/chat/completions",
headers={
"Authorization": f"Bearer {os.getenv('HOLYSHEEP_API_KEY')}",
"Content-Type": "application/json"
},
json={
"model": "gpt-4.1",
"messages": [{"role": "user", "content": prompt}],
"max_tokens": 800,
"temperature": 0.7
}
)
if response.status_code == 200:
email_content = response.json()["choices"][0]["message"]["content"]
# In production: Send email via your email service provider
logger.info(f"Generated confirmation email for order {order_ref}")
Testing Your Integration
Use MercadoPago's sandbox environment to test without processing real transactions. Here's a test script that validates your entire payment flow:
#!/usr/bin/env python3
"""Integration test suite for MercadoPago + HolySheep AI setup."""
import asyncio
import pytest
from unittest.mock import patch, AsyncMock
import os
os.environ["MERCADO_PAGO_ACCESS_TOKEN"] = "APP_USR-test_token_12345"
os.environ["HOLYSHEEP_API_KEY"] = "test_api_key"
os.environ["WEBHOOK_SECRET"] = "test_secret"
from main import MercadoPagoClient, MercadoPagoError
@pytest.fixture
def client():
return MercadoPagoClient()
class TestMercadoPagoIntegration:
@pytest.mark.asyncio
async def test_create_preference_success(self, client):
"""Test successful payment preference creation."""
with patch("httpx.AsyncClient.post") as mock_post:
mock_post.return_value = AsyncMock(
status_code=201,
json=lambda: {
"id": "preference_123",
"init_point": "https://www.mercadopago.com.ar/checkout/v1/redirect?pref_id=preference_123",
"sandbox_init_point": "https://sandbox.mercadopago.com.ar/checkout/v1/redirect?pref_id=preference_123"
}
)
result = await client.create_payment_preference(
items=[{
"title": "Test Product",
"quantity": 1,
"currency_id": "ARS",
"unit_price": 100.00
}],
payer_email="[email protected]",
external_reference="TEST-001"
)
assert result["id"] == "preference_123"
assert "init_point" in result
@pytest.mark.asyncio
async def test_create_preference_failure(self, client):
"""Test handling of API errors during preference creation."""
with patch("httpx.AsyncClient.post") as mock_post:
mock_post.return_value = AsyncMock(
status_code=401,
text="Unauthorized: Invalid access token"
)
with pytest.raises(MercadoPagoError) as exc_info:
await client.create_payment_preference(
items=[{"title": "Test", "quantity": 1, "currency_id": "ARS", "unit_price": 10}],
payer_email="[email protected]",
external_reference="TEST-002"
)
assert "401" in str(exc_info.value)
@pytest.mark.asyncio
async def test_ai_integration_fallback(self, client):
"""Test graceful degradation when AI service is unavailable."""
with patch("httpx.AsyncClient.get") as mock_get, \
patch("httpx.AsyncClient.post") as mock_post:
# Mock successful payment fetch
mock_get.return_value = AsyncMock(
status_code=200,
json=lambda: {"id": "payment_123", "status": "approved", "transaction_amount": 15000}
)
# Mock AI service failure
mock_post.return_value = AsyncMock(status_code=503, text="Service Unavailable")
result = await client.verify_payment_with_ai("payment_123", 15000)
# Should still return payment data even if AI analysis fails
assert result["payment"]["id"] == "payment_123"
assert result["ai_analysis"] is None
if __name__ == "__main__":
pytest.main([__file__, "-v"])
Common Errors and Fixes
1. Error: "ConnectionError: Connection timeout after 30000ms"
Symptom: API requests to MercadoPago fail with timeout errors, particularly when running from Argentine data centers or behind corporate proxies.
Root Cause: MercadoPago's default endpoints route through CDN nodes that may not be optimized for Argentine network topology. Additionally, some corporate proxies block specific IP ranges.
# Fix: Explicitly set the target country/region in your client initialization
import httpx
async def create_configured_client():
"""Create an httpx client with Argentine-optimized routing."""
transport = httpx.HTTPTransport(
retries=3,
local_address="0.0.0.0" # Helps with certain proxy configurations
)
client = httpx.AsyncClient(
timeout=httpx.Timeout(60.0, connect=10.0), # Extended timeout for Argentina
limits=httpx.Limits(max_keepalive_connections=20, max_connections=100),
transport=transport,
proxies={ # If you need explicit proxy configuration
"http://": os.getenv("HTTP_PROXY"),
"https://": os