Saltar a contenido

🔌 API de Ingesta

La API de Ingesta es el componente de la Capa 1 (Backend 1) responsable de recibir y validar los datos de ofertas P2P enviados por los Workers externos. Su diseño prioriza la seguridad y la integridad de los datos.

Endpoint Principal de Ingesta

POST /api/v1/binance/offers

Este endpoint es el punto de entrada para que los Workers envíen los datos de ofertas P2P recolectados.

  • Descripción: Recibe un lote de ofertas P2P de Binance, las valida y las almacena en la base de datos. También registra la ejecución del Worker (run).
  • Autenticación: Requiere una API Key válida en el encabezado X-API-Key.
  • Cuerpo de la Solicitud (Request Body): Un array de objetos OfferCreate.

Ejemplo de OfferCreate Schema (Pydantic)

from pydantic import BaseModel, Field
from typing import List, Optional

class PaymentMethodSchema(BaseModel):
    name: str = Field(..., description="Nombre del método de pago (ej. 'Mercado Pago', 'Transferencia Bancaria')")

class OfferCreate(BaseModel):
    asset: str = Field(..., description="Activo de la oferta (ej. 'USDT', 'BTC')")
    fiat: str = Field(..., description="Moneda fiat de la oferta (ej. 'ARS', 'USD')")
    price: float = Field(..., description="Precio de la oferta")
    trade_type: str = Field(..., description="Tipo de operación ('BUY' o 'SELL')")
    amount: float = Field(..., description="Cantidad total disponible de la oferta")
    min_single_trans_amount: float = Field(..., description="Monto mínimo por transacción")
    max_single_trans_amount: float = Field(..., description="Monto máximo por transacción")
    payments: List[PaymentMethodSchema] = Field(..., description="Lista de métodos de pago aceptados")
    advertiser_id: str = Field(..., description="ID del anunciante/comerciante")
    advertiser_nick: str = Field(..., description="Nickname del anunciante/comerciante")
    month_order_count: Optional[int] = Field(None, description="Número de órdenes en el último mes")
    month_finish_rate: Optional[float] = Field(None, description="Tasa de finalización en el último mes")
    positive_comment_rate: Optional[float] = Field(None, description="Tasa de comentarios positivos")
    taker_coin_count: Optional[int] = Field(None, description="Número de monedas tomadas (para SELL)")
    publisher_type: Optional[str] = Field(None, description="Tipo de publicador (ej. 'merchant')")
    # Otros campos relevantes que puedan venir del scraper

Ejemplo de Solicitud (Request)

POST /api/v1/binance/offers HTTP/1.1
X-API-Key: tu_api_key_secreta
Content-Type: application/json

[
  {
    "asset": "USDT",
    "fiat": "ARS",
    "price": 1050.50,
    "trade_type": "BUY",
    "amount": 1000.00,
    "min_single_trans_amount": 100.00,
    "max_single_trans_amount": 5000.00,
    "payments": [
      { "name": "Mercado Pago" },
      { "name": "Transferencia Bancaria" }
    ],
    "advertiser_id": "123456789",
    "advertiser_nick": "ComercianteEjemplo",
    "month_order_count": 50,
    "month_finish_rate": 0.98,
    "positive_comment_rate": 0.99,
    "publisher_type": "merchant"
  },
  {
    "asset": "USDT",
    "fiat": "ARS",
    "price": 1051.00,
    "trade_type": "SELL",
    "amount": 500.00,
    "min_single_trans_amount": 50.00,
    "max_single_trans_amount": 2000.00,
    "payments": [
      { "name": "Ualá" }
    ],
    "advertiser_id": "987654321",
    "advertiser_nick": "OtroComerciante",
    "month_order_count": 120,
    "month_finish_rate": 0.95,
    "positive_comment_rate": 0.97
  }
]

Ejemplo de Respuesta (Response)

Éxito (HTTP 200 OK):

HTTP/1.1 200 OK
Content-Type: application/json

{
  "message": "Offers processed successfully",
  "run_id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
  "total_offers_received": 2,
  "offers_saved": 2
}

Error (HTTP 401 Unauthorized - API Key inválida):

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "detail": "Invalid API Key"
}

Error (HTTP 422 Unprocessable Entity - Datos inválidos):

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "detail": [
    {
      "loc": [
        "body",
        0,
        "asset"
      ],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

Error (HTTP 503 Service Unavailable - Error interno del servidor):

HTTP/1.1 503 Service Unavailable
Content-Type: application/json

{
  "detail": "ScraperError: Failed to process some offers due to database issue."
}

Consideraciones de Seguridad

  • API Keys: Las API Keys deben ser tratadas como credenciales sensibles y no deben ser expuestas en el código fuente o en logs públicos.
  • Validación de Entrada: La API realiza una validación estricta de los datos recibidos para prevenir inyecciones y asegurar la integridad de la base de datos.
  • Manejo de Errores: Los errores son manejados de forma controlada, evitando exponer detalles internos del servidor al cliente.