Introducción a las APIs en Perfex
Perfex CRM incluye soporte nativo para APIs REST que permite exponer los datos de tu módulo a aplicaciones externas: apps móviles, integraciones con otros sistemas o automatizaciones.
💡 ¿Por qué crear una API?
- Integrar con aplicaciones móviles
- Conectar con sistemas externos (ERP, CRM)
- Automatizar procesos con Zapier/n8n
- Crear dashboards externos
Estructura de Endpoints
Define tus endpoints siguiendo el estándar REST:
Lista todos los productos
Obtiene un producto específico
Crea un nuevo producto
Actualiza un producto existente
Elimina un producto
Crear el Controlador API
Crea un controlador específico para la API que maneje las peticiones REST:
<?php
defined('BASEPATH') or exit('No direct script access allowed');
class Mi_modulo_api extends AdminController
{
private $api_key;
public function __construct()
{
parent::__construct();
$this->load->model('productos_model');
// Validar autenticación API
$this->validar_api_key();
}
/**
* Validar API Key en headers
*/
private function validar_api_key()
{
$api_key = $this->input->get_request_header('X-API-KEY', TRUE);
if (!$api_key) {
$this->responder_error('API Key requerida', 401);
}
// Verificar key en base de datos
$valida = $this->db
->where('api_key', $api_key)
->where('activo', 1)
->get(db_prefix() . 'mi_modulo_api_keys')
->row();
if (!$valida) {
$this->responder_error('API Key inválida', 403);
}
$this->api_key = $valida;
}
/**
* GET /api/mi_modulo/productos
*/
public function productos()
{
$method = $this->input->method();
switch ($method) {
case 'get':
$this->listar_productos();
break;
case 'post':
$this->crear_producto();
break;
default:
$this->responder_error('Método no permitido', 405);
}
}
/**
* GET /api/mi_modulo/productos/{id}
*/
public function producto($id = null)
{
$method = $this->input->method();
if (!$id) {
$this->responder_error('ID requerido', 400);
}
switch ($method) {
case 'get':
$this->obtener_producto($id);
break;
case 'put':
$this->actualizar_producto($id);
break;
case 'delete':
$this->eliminar_producto($id);
break;
default:
$this->responder_error('Método no permitido', 405);
}
}
}
Métodos CRUD
Implementa los métodos que manejan cada operación:
/**
* Listar todos los productos
*/
private function listar_productos()
{
// Parámetros de paginación
$page = (int) $this->input->get('page') ?: 1;
$limit = (int) $this->input->get('limit') ?: 20;
$offset = ($page - 1) * $limit;
// Filtros opcionales
$categoria = $this->input->get('categoria');
$busqueda = $this->input->get('q');
$this->db->select('*');
$this->db->from(db_prefix() . 'mi_modulo_productos');
$this->db->where('activo', 1);
if ($categoria) {
$this->db->where('categoria_id', $categoria);
}
if ($busqueda) {
$this->db->like('nombre', $busqueda);
}
// Total para paginación
$total = $this->db->count_all_results('', false);
// Obtener resultados paginados
$productos = $this->db
->limit($limit, $offset)
->get()
->result_array();
$this->responder([
'data' => $productos,
'pagination' => [
'page' => $page,
'limit' => $limit,
'total' => $total,
'total_pages' => ceil($total / $limit)
]
]);
}
/**
* Crear nuevo producto
*/
private function crear_producto()
{
// Obtener JSON del body
$json = file_get_contents('php://input');
$data = json_decode($json, true);
// Validar campos requeridos
$requeridos = ['nombre', 'precio'];
foreach ($requeridos as $campo) {
if (empty($data[$campo])) {
$this->responder_error("Campo {$campo} es requerido", 422);
}
}
// Sanitizar datos
$producto = [
'nombre' => strip_tags($data['nombre']),
'descripcion' => strip_tags($data['descripcion'] ?? ''),
'precio' => (float) $data['precio'],
'stock' => (int) ($data['stock'] ?? 0),
'datecreated' => date('Y-m-d H:i:s')
];
$this->db->insert(db_prefix() . 'mi_modulo_productos', $producto);
$id = $this->db->insert_id();
$this->responder([
'message' => 'Producto creado exitosamente',
'id' => $id
], 201);
}
Helpers de Respuesta
Crea métodos helper para formatear las respuestas JSON:
/**
* Responder con JSON exitoso
*/
private function responder($data, $status = 200)
{
$this->output
->set_status_header($status)
->set_content_type('application/json')
->set_output(json_encode([
'success' => true,
...$data
]));
exit;
}
/**
* Responder con error
*/
private function responder_error($mensaje, $status = 400)
{
$this->output
->set_status_header($status)
->set_content_type('application/json')
->set_output(json_encode([
'success' => false,
'error' => [
'code' => $status,
'message' => $mensaje
]
]));
exit;
}
🔒 Seguridad Importante
Nunca expongas datos sensibles en tu API. Valida siempre los permisos del usuario asociado a la API key y limita los campos que se devuelven.
Registrar Rutas
Añade las rutas de tu API en el archivo de rutas del módulo:
// config/routes.php del módulo
// Rutas API
$route['api/mi_modulo/productos'] = 'mi_modulo/mi_modulo_api/productos';
$route['api/mi_modulo/productos/(:num)'] = 'mi_modulo/mi_modulo_api/producto/$1';
Ejemplo de Uso
# Listar productos
curl -X GET "https://tucrm.com/api/mi_modulo/productos?page=1&limit=10" \
-H "X-API-KEY: tu_api_key_aqui"
# Crear producto
curl -X POST "https://tucrm.com/api/mi_modulo/productos" \
-H "X-API-KEY: tu_api_key_aqui" \
-H "Content-Type: application/json" \
-d '{"nombre": "Producto Nuevo", "precio": 99.99}'
# Respuesta exitosa
{
"success": true,
"message": "Producto creado exitosamente",
"id": 123
}
✅ API Lista
Ya tienes una API REST funcional con autenticación, validación y respuestas estructuradas. Puedes extenderla con más endpoints según las necesidades de tu módulo.