Volver a la documentación

Informes psicológicos (occidental)

Informes psicológicos (occidental)

Generar informes premium completos

POST https://api.freeastroapi.com/api/v1/natal/calculate

Encabezado de autenticación: x-api-key

Usa el endpoint natal con psychological_report.enabled=true. En producción, prioriza el modo asíncrono y el polling según la cadencia del servidor, o recibe los informes terminados mediante callback webhook.

La generación de un informe completo suele tardar 3-4 minutos. Es normal: el informe se produce mediante una cadena de varias pasadas (síntesis, redacción de capítulos, revisión y validación).

Reintentos seguros con Idempotency-Key

Las solicitudes astrológicas POST autenticadas y facturables aceptan el encabezado opcional Idempotency-Key: <clave de operacion unica generada por el cliente>. Reutiliza la misma clave solo para reintentar exactamente el mismo method, path, query string y JSON body después de un timeout o error de red.

Una repetición completada devuelve la primera respuesta con Idempotency-Replayed: true, no vuelve a ejecutar el cálculo y no consume cuota adicional. Las claves se conservan durante unas 24 horas.

Reutilizar una clave con una solicitud modificada devuelve 409 idempotency_key_reused. Un duplicado mientras la primera solicitud sigue en curso devuelve 409 request_in_progress con Retry-After.

Carta de prueba sin crédito

Usa este payload sintético exacto para probar la generación de informes sin gastar créditos de informe. Esta excepción solo se aplica a esta firma de nacimiento concreta.

{
  "name": "Synthetic Demo Candidate",
  "year": 1992,
  "month": 11,
  "day": 23,
  "hour": 14,
  "minute": 17,
  "city": "Lisbon",
  "tz_str": "Auto",
  "psychological_report": {
    "enabled": true,
    "mode": "async",
    "style": "standard",
    "markdown": false
  }
}

Para solicitar una salida Markdown, envía el mismo payload con psychological_report.markdown=true:

{
  "name": "Synthetic Demo Candidate",
  "year": 1992,
  "month": 11,
  "day": 23,
  "hour": 14,
  "minute": 17,
  "city": "Lisbon",
  "tz_str": "Auto",
  "psychological_report": {
    "enabled": true,
    "mode": "async",
    "style": "standard",
    "markdown": true
  }
}

Cualquier otro dato de nacimiento sigue la facturación normal en créditos de informe.

Descargar salidas de ejemplo completas

Estos archivos son salidas completas generadas desde la misma carta sintética de demostración y se ofrecen como snapshots fijos para previsualizar la integración.

Parámetros de solicitud

ParámetroTypeReqDescription
psychological_report.enabledbooleanActiva la generación del informe. Por defecto: false.
psychological_report.modestringNoModo de entrega del informe: async o sync. Por defecto: async.
psychological_report.stylestringNoEstilo del informe: standard o jungian_parental. Por defecto: standard.
psychological_report.markdownbooleanNoIncluye report_markdown en las respuestas completadas. Por defecto: false.
psychological_report.include_natal_chart_in_responsebooleanNoIncluye el payload de la carta natal en la respuesta de polling del informe. Por defecto: false.
psychological_report.debugbooleanNoIncluye métricas internas de validación debug en la respuesta. Por defecto: false.

Solicitud de inicio rápido

curl -X POST "https://api.freeastroapi.com/api/v1/natal/calculate" \
 -H "Content-Type: application/json" \
 -H "x-api-key: YOUR_API_KEY" \
 -d '{
    "name": "Synthetic Demo Candidate",
    "year": 1992,
    "month": 11,
    "day": 23,
    "hour": 14,
    "minute": 17,
    "city": "Lisbon",
    "tz_str": "Auto",
    "psychological_report": {
      "enabled": true,
      "mode": "async"
    }
 }'

Flujo asíncrono (integración mínima viable)

  1. Crea la solicitud de informe con mode: "async" usando la carta de prueba sin crédito anterior.
  2. Lee job_id y next_poll_after_seconds.
  3. Consulta GET /api/v1/natal/report/{job_id} respetando la cadencia del servidor.
  4. Para la carta de prueba, verifica credits_used: 0.
  5. Cuando el estado sea completed, lee report_metadata y usa report_content o report_markdown según la opción solicitada.
{
  "subject": { "...": "normal natal chart payload..." },
  "credits_used": 0,
  "psychological_report": {
    "status": "pending",
    "mode": "async",
    "style": "standard",
    "job_id": "7a7f3f9f-...",
    "fetch_url": "/api/v1/natal/report/7a7f3f9f-...",
    "credits_used": 0,
    "next_poll_after_seconds": 15
  }
}
{
  "job_id": "7a7f3f9f-...",
  "status": "completed",
  "credits_used": 0,
  "report_metadata": {
    "report_id": "e5efe6ea-...",
    "title": "Jane Example Natal Psychological Report",
    "generated_at": "2026-03-21T11:44:09.531Z",
    "provider": "openai-compatible",
    "model": "gpt-5.3-chat-latest",
    "summary": "Core report summary...",
    "word_count": 7350
  },
  "report_markdown": "## Introduction ... (full markdown report)"
}

Créditos y caché

  • Este flujo usa créditos especiales de informe, no la cuota normal de solicitudes.
  • La carta sintética de prueba publicada está exenta y devuelve credits_used: 0 para probar el endpoint.
  • Una generación nueva de informe consume 1 crédito de informe (credits_used: 1).
  • Una respuesta servida desde caché para los mismos datos de nacimiento reutiliza el informe almacenado y no consume crédito adicional.
  • Usa directamente report_content.chapters[].sections[].paragraphs[] para construir tu interfaz PDF.

Formato de salida

Las respuestas completadas siempre incluyen report_metadata. El cuerpo de salida es exclusivo: con psychological_report.markdown=false (por defecto), recibes report_content; con psychological_report.markdown=true recibes report_markdown.

Errores frecuentes

  • Falta el encabezado x-api-key.
  • Polling demasiado rápido en lugar de respetar next_poll_after_seconds / Retry-After.
  • callback_url enviado sin callback_signing_secret.
  • Olvidar que Markdown debe activarse explícitamente. Define psychological_report.markdown=true si quieres report_markdown.

Avanzado: callback webhook (opcional)

Esta opción es avanzada y opcional. Si envías callback_url y callback_signing_secret, la API envía un callback firmado cuando el job está completed o failed.

ParámetroTypeReqDescription
psychological_report.callback_urlstringNoEndpoint HTTPS de callback para eventos de informe completed/failed. Por defecto: null.
psychological_report.callback_signing_secretstringNoSecreto de firma webhook. Requerido cuando callback_url está definido. Por defecto: null.
{
  "event": "psychological_report.completed",
  "job_id": "7a7f3f9f-...",
  "status": "completed",
  "credits_used": 1,
  "report_metadata": { "...": "same metadata object as polling response" },
  "report_markdown": "## Introduction ...",
  "created_at": "2026-03-21T11:44:09.531Z"
}

Headers:
X-FreeAstro-Event: psychological_report.completed
X-FreeAstro-Timestamp: 1711025109
X-FreeAstro-Signature: <HMAC_SHA256_HEX>
import crypto from "node:crypto";
import express from "express";

const app = express();
app.use(express.raw({ type: "application/json" }));

app.post("/webhooks/freeastro/report", (req, res) => {
  const rawBody = req.body.toString("utf8");
  const timestamp = req.header("X-FreeAstro-Timestamp") || "";
  const signature = req.header("X-FreeAstro-Signature") || "";
  const secret = process.env.FREE_ASTRO_CALLBACK_SECRET || "";

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex");

  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    return res.status(401).send("invalid signature");
  }

  const event = JSON.parse(rawBody);
  // Save report by event.job_id, then ack
  return res.status(200).json({ ok: true });
});