feat(webhooks): dispatch async generation_request.created and creative.created events to n8n with 60s retry

This commit is contained in:
Marcos Fargas
2026-10-13 01:17:26 +02:00
parent 66d34853e6
commit 2a1629cda8
4 changed files with 112 additions and 25 deletions

View File

@@ -1,5 +1,6 @@
import { NextRequest, NextResponse } from 'next/server';
import { authenticateIntegrationRequest } from '@/lib/integrations-auth';
import { dispatchN8nWebhookAsync } from '@/lib/creatives-webhooks';
import { createClient } from '@supabase/supabase-js';
export async function POST(req: NextRequest) {
@@ -66,9 +67,10 @@ export async function POST(req: NextRequest) {
cta: c.cta || null,
asset_url: c.asset_url || null,
thumbnail_url: c.thumbnail_url || null,
asset_final: Boolean(c.asset_final ?? false),
status: 'borrador', // nacen siempre en borrador
visibility: 'agency', // nacen siempre en agency
created_by: 'claude', // creadas por Claude
created_by: c.created_by || 'claude', // creadas por Claude
parent_id: c.parent_id || defaultParentId,
generation_request_id: c.generation_request_id || genRequestId || null,
meta,
@@ -84,7 +86,34 @@ export async function POST(req: NextRequest) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
// Registrar cada creación en creative_events con actor 'claude'
const { data: tenant } = await adminClient
.from('tenants')
.select('id, name, slug, drive_folder_id, canva_templates')
.eq('id', tenantId)
.maybeSingle();
const defaultBpsTemplate = process.env.BPS_CANVA_TEMPLATE_ID || 'EAHRb38v_WY';
let canvaTemplates = tenant?.canva_templates || {};
if (
tenant?.slug === 'bps' &&
(!canvaTemplates || Object.keys(canvaTemplates).length === 0)
) {
canvaTemplates = {
'foto-con-franja': defaultBpsTemplate,
tipografico: null,
default: defaultBpsTemplate,
};
}
const clientInfo = {
id: tenant?.id || tenantId,
name: tenant?.name || null,
slug: tenant?.slug || 'bps',
drive_folder_id: tenant?.drive_folder_id || null,
canva_templates: canvaTemplates,
};
// Registrar cada creación en creative_events con actor 'claude' y disparar creative.created si created_by='claude' y asset_final=false
for (const c of inserted || []) {
await adminClient.from('creative_events').insert({
tenant_id: tenantId,
@@ -100,6 +129,17 @@ export async function POST(req: NextRequest) {
},
visibility: 'agency',
});
if (c.created_by === 'claude' && c.asset_final === false) {
dispatchN8nWebhookAsync('creative.created', {
creative: {
...c,
client_id: c.tenant_id,
meta: c.meta || {},
client: clientInfo,
},
});
}
}
return NextResponse.json({