@extends('layouts.app') @section('content')

Documentación de API

Integración completa con tu sitio web mediante API RESTful

Información General
Base URL
{{ config('app.url') }}/api/public
Autenticación

Las rutas públicas de la API no requieren autenticación. Para operaciones administrativas, se requiere token de autenticación.

Formato de Respuesta

Todas las respuestas se devuelven en formato JSON.

{
    "success": true,
    "data": { ... },
    "message": "Operación exitosa"
}
Códigos de Estado HTTP
  • 200 - OK: Solicitud exitosa
  • 201 - Created: Recurso creado exitosamente
  • 400 - Bad Request: Error en los datos enviados
  • 404 - Not Found: Recurso no encontrado
  • 422 - Unprocessable Entity: Error de validación
  • 500 - Internal Server Error: Error del servidor
Consejos de Uso
  • Valida siempre las respuestas de la API
  • Maneja errores apropiadamente
  • Usa HTTPS en producción
  • Implementa rate limiting en tu cliente
  • Registra los errores para debugging
Listar Proyectos Activos

Endpoint: GET /api/public/projects

Descripción: Obtiene la lista de proyectos activos disponibles para crear tickets.

Ejemplo de Solicitud - JavaScript (Fetch)
fetch('{{ config('app.url') }}/api/public/projects', {
    method: 'GET',
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }
})
.then(response => response.json())
.then(data => {
    console.log('Proyectos:', data.data);
})
.catch(error => {
    console.error('Error:', error);
});
Ejemplo de Solicitud - PHP (cURL)
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, '{{ config('app.url') }}/api/public/projects');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Accept: application/json'
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode === 200) {
    $projects = json_decode($response, true);
    print_r($projects['data']);
}
Respuesta Exitosa (200)
{
    "success": true,
    "data": [
        {
            "id": 1,
            "name": "Sitio Web Corporativo",
            "description": "Mantenimiento del sitio web principal",
            "status": "activo"
        },
        {
            "id": 2,
            "name": "Aplicación Móvil",
            "description": "Desarrollo de app móvil",
            "status": "activo"
        }
    ]
}
Crear Ticket desde Web Pública

Endpoint: POST /api/public/tickets

Descripción: Crea un nuevo ticket desde un formulario público en tu sitio web.

Parámetros Requeridos
Campo Tipo Descripción
title string Título del ticket (mínimo 10 caracteres)
description string Descripción detallada del problema
project_id integer ID del proyecto (obtener de /api/public/projects)
priority string Prioridad: baja, media, alta, critica
requester_email email Email del solicitante
Ejemplo de Solicitud - JavaScript (Fetch)
const ticketData = {
    title: 'Problema con el formulario de contacto',
    description: 'El formulario de contacto no envía los correos correctamente...',
    project_id: 1,
    priority: 'alta',
    requester_email: 'cliente@ejemplo.com'
};

fetch('{{ config('app.url') }}/api/public/tickets', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    },
    body: JSON.stringify(ticketData)
})
.then(response => response.json())
.then(data => {
    if (data.success) {
        alert('Ticket creado: ' + data.data.ticket_number);
    } else {
        alert('Error: ' + data.message);
    }
})
.catch(error => {
    console.error('Error:', error);
});
Ejemplo de Solicitud - PHP (cURL)
$ticketData = [
    'title' => 'Problema con el formulario de contacto',
    'description' => 'El formulario de contacto no envía los correos correctamente...',
    'project_id' => 1,
    'priority' => 'alta',
    'requester_email' => 'cliente@ejemplo.com'
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, '{{ config('app.url') }}/api/public/tickets');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($ticketData));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Accept: application/json'
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$result = json_decode($response, true);

if ($httpCode === 201) {
    echo "Ticket creado: " . $result['data']['ticket_number'];
} else {
    echo "Error: " . $result['message'];
}
Respuesta Exitosa (201)
{
    "success": true,
    "message": "Ticket creado exitosamente",
    "data": {
        "id": 42,
        "ticket_number": "TK2025100042",
        "title": "Problema con el formulario de contacto",
        "status": "abierto",
        "priority": "alta",
        "created_at": "2025-10-30T10:30:00.000000Z"
    }
}
Respuesta de Error (422)
{
    "success": false,
    "message": "Error de validación",
    "errors": {
        "title": ["El título debe tener al menos 10 caracteres."],
        "requester_email": ["El email no es válido."]
    }
}
Ejemplo de Formulario HTML Completo
<!-- Formulario de Creación de Ticket -->
<form id="ticketForm">
    <div class="mb-3">
        <label for="project" class="form-label">Proyecto</label>
        <select class="form-select" id="project" name="project_id" required>
            <option value="">Seleccione un proyecto...</option>
        </select>
    </div>
    
    <div class="mb-3">
        <label for="title" class="form-label">Título</label>
        <input type="text" class="form-control" id="title" name="title" required>
    </div>
    
    <div class="mb-3">
        <label for="description" class="form-label">Descripción</label>
        <textarea class="form-control" id="description" name="description" rows="4" required></textarea>
    </div>
    
    <div class="mb-3">
        <label for="priority" class="form-label">Prioridad</label>
        <select class="form-select" id="priority" name="priority" required>
            <option value="baja">Baja</option>
            <option value="media" selected>Media</option>
            <option value="alta">Alta</option>
            <option value="critica">Crítica</option>
        </select>
    </div>
    
    <div class="mb-3">
        <label for="email" class="form-label">Email</label>
        <input type="email" class="form-control" id="email" name="requester_email" required>
    </div>
    
    <button type="submit" class="btn btn-primary">Crear Ticket</button>
</form>

<script>
const API_BASE = '{{ config('app.url') }}/api/public';

// Cargar proyectos al inicio
fetch(`${API_BASE}/projects`)
    .then(response => response.json())
    .then(data => {
        const select = document.getElementById('project');
        data.data.forEach(project => {
            const option = document.createElement('option');
            option.value = project.id;
            option.textContent = project.name;
            select.appendChild(option);
        });
    });

// Manejar envío del formulario
document.getElementById('ticketForm').addEventListener('submit', function(e) {
    e.preventDefault();
    
    const formData = {
        title: document.getElementById('title').value,
        description: document.getElementById('description').value,
        project_id: parseInt(document.getElementById('project').value),
        priority: document.getElementById('priority').value,
        requester_email: document.getElementById('email').value
    };
    
    fetch(`${API_BASE}/tickets`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        },
        body: JSON.stringify(formData)
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            alert('¡Ticket creado exitosamente! Número: ' + data.data.ticket_number);
            document.getElementById('ticketForm').reset();
        } else {
            alert('Error: ' + data.message);
        }
    })
    .catch(error => {
        console.error('Error:', error);
        alert('Ocurrió un error al crear el ticket');
    });
});
</script>
@endsection