PageSourceSearch

https://opencopy.ai/build/assets/webhook-integration-CXf6k7E4.js

js opencopy.ai collected 2026-10-05 14:32:11 UTC 34,055 bytes, 181 lines download raw bytes

1import{c as $e,b as ze,r as Ie,j as t,L as h,H as Be}from"./app-Da8ydggO.js";import{A as De}from"./app-logo-icon-CxKMCRLi.js";import{B as Ue}from"./badge-DMIDZd3R.js";import{B as F}from"./button-BmDgkJaU.js";import{h as We,d as Pe,b as qe,r as Le}from"./index-BLAl4Rvk.js";import{Z as Me}from"./zap-rJ9yI3zJ.js";import{S as Ye}from"./shield-CPg1GzE6.js";import{c as Ge}from"./createLucideIcon-C4W1dCfJ.js";import{C as Ve}from"./check-Ci5l8BE1.js";import{C as Je}from"./copy-3r8Cbq7x.js";/* empty css            *//**
2 * @license lucide-react v0.475.0 - ISC
3 *
4 * This source code is licensed under the ISC license.
5 * See the LICENSE file in the root directory of this source tree.
6 */const Xe=[["path",{d:"m18 16 4-4-4-4",key:"1inbqp"}],["path",{d:"m6 8-4 4 4 4",key:"15zrgr"}],["path",{d:"m14.5 4-5 16",key:"e7oirm"}]],Ke=Ge("CodeXml",Xe);function u(e){const s=$e.c(13),{code:a,language:x}=e,m=x===void 0?"json":x,[r,i]=Ie.useState(!1);let l;s[0]!==a?(l=()=>{navigator.clipboard.writeText(a),i(!0),setTimeout(()=>i(!1),2e3)},s[0]=a,s[1]=l):l=s[1];const o=l;let n;s[2]!==r?(n=r?t.jsx(Ve,{className:"h-4 w-4 text-green-400"}):t.jsx(Je,{className:"h-4 w-4 text-slate-300"}),s[2]=r,s[3]=n):n=s[3];let c;s[4]!==o||s[5]!==n?(c=t.jsx("button",{onClick:o,className:"absolute top-3 right-3 rounded-md bg-slate-700 p-2 opacity-0 transition-opacity group-hover:opacity-100 hover:bg-slate-600",title:"Copy to clipboard",children:n}),s[4]=o,s[5]=n,s[6]=c):c=s[6];const b=`language-${m}`;let d;s[7]!==a||s[8]!==b?(d=t.jsx("pre",{className:"overflow-x-auto rounded-lg bg-slate-900 p-4 text-sm text-slate-300",children:t.jsx("code",{className:b,children:a})}),s[7]=a,s[8]=b,s[9]=d):d=s[9];let p;return s[10]!==c||s[11]!==d?(p=t.jsxs("div",{className:"group relative",children:[c,d]}),s[10]=c,s[11]=d,s[12]=p):p=s[12],p}function He(e){const s=$e.c(10),{icon:a,title:x,description:m}=e;let r;s[0]!==a?(r=t.jsx("div",{className:"mb-4 flex h-10 w-10 items-center justify-center rounded-lg bg-[#00AAFF]/10",children:t.jsx(a,{className:"h-5 w-5 text-[#00AAFF]"})}),s[0]=a,s[1]=r):r=s[1];let i;s[2]!==x?(i=t.jsx("h3",{className:"mb-2 font-semibold text-slate-900 dark:text-white",children:x}),s[2]=x,s[3]=i):i=s[3];let l;s[4]!==m?(l=t.jsx("p",{className:"text-sm text-slate-600 dark:text-slate-400",children:m}),s[4]=m,s[5]=l):l=s[5];let o;return s[6]!==r||s[7]!==i||s[8]!==l?(o=t.jsxs("div",{className:"rounded-lg border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900",children:[r,i,l]}),s[6]=r,s[7]=i,s[8]=l,s[9]=o):o=s[9],o}const Ze=`{
7  "event_type": "publish_article",
8  "timestamp": "2025-01-15T10:30:00+00:00",
9  "data": {
10    "article": {
11      "id": 42,
12      "title": "How to Boost Your SEO Rankings in 2025",
13      "slug": "how-to-boost-seo-rankings-2025",
14      "content_html": "<h2>Introduction</h2><p>Search engine optimization...</p>",
15      "content_markdown": "## Introduction\\n\\nSearch engine optimization...",
16      "meta_description": "Learn proven SEO strategies to improve your search rankings and drive organic traffic in 2025.",
17      "excerpt": "Learn proven SEO strategies to improve your search rankings...",
18      "image_url": "https://example.com/storage/articles/featured-image.png",
19      "tags": ["SEO", "Marketing", "Digital Strategy"],
20      "created_at": "2025-01-15T10:30:00+00:00",
21      "word_count": 1847,
22      "reading_time_minutes": 8
23    }
24  }
25}`,Qe=`{
26  "event_type": "test",
27  "timestamp": "2025-01-15T10:30:00+00:00",
28  "data": {
29    "article": {
30      "id": 0,
31      "title": "Test Connection",
32      "slug": "test-connection",
33      "content_html": "<p>This is a test payload to verify your webhook endpoint.</p>",
34      "content_markdown": "This is a test payload to verify your webhook endpoint.",
35      "meta_description": "Test payload",
36      "created_at": "2025-01-15T10:30:00+00:00"
37    }
38  }
39}`,et=`<?php
40// Laravel example webhook handler
41
42Route::post('/webhook/opencopy', function (Request $request) {
43    // Verify the Bearer token
44    $token = $request->bearerToken();
45    if ($token !== config('services.opencopy.webhook_secret')) {
46        return response()->json(['error' => 'Unauthorized'], 401);
47    }
48
49    $payload = $request->all();
50    $eventType = $payload['event_type'];
51
52    // Handle test events
53    if ($eventType === 'test') {
54        return response()->json([
55            'success' => true,
56            'message' => 'Webhook configured successfully'
57        ]);
58    }
59
60    // Handle article publish events
61    if ($eventType === 'publish_article') {
62        $article = $payload['data']['article'];
63
64        // Create your blog post
65        $post = Post::create([
66            'title' => $article['title'],
67            'slug' => $article['slug'],
68            'content' => $article['content_html'],
69            'excerpt' => $article['excerpt'],
70            'meta_description' => $article['meta_description'],
71            'featured_image' => $article['image_url'],
72        ]);
73
74        return response()->json([
75            'id' => $post->id,
76            'url' => url("/blog/{$post->slug}"),
77        ]);
78    }
79
80    return response()->json(['success' => true]);
81});`,tt=`// Express.js example webhook handler
82
83const express = require('express');
84const app = express();
85
86app.use(express.json());
87
88app.post('/webhook/opencopy', (req, res) => {
89    // Verify the Bearer token
90    const authHeader = req.headers.authorization;
91    const token = authHeader?.replace('Bearer ', '');
92
93    if (token !== process.env.OPENCOPY_WEBHOOK_SECRET) {
94        return res.status(401).json({ error: 'Unauthorized' });
95    }
96
97    const { event_type, data } = req.body;
98
99    // Handle test events
100    if (event_type === 'test') {
101        return res.json({
102            success: true,
103            message: 'Webhook configured successfully'
104        });
105    }
106
107    // Handle article publish events
108    if (event_type === 'publish_article') {
109        const article = data.article;
110
111        // Create your blog post (example using a database)
112        const post = await createBlogPost({
113            title: article.title,
114            slug: article.slug,
115            content: article.content_html,
116            excerpt: article.excerpt,
117            metaDescription: article.meta_description,
118            featuredImage: article.image_url,
119        });
120
121        return res.json({
122            id: post.id,
123            url: \`https://yourdomain.com/blog/\${post.slug}\`,
124        });
125    }
126
127    res.json({ success: true });
128});`,st=`// Next.js API Route (app/api/webhook/opencopy/route.ts)
129
130import { NextRequest, NextResponse } from 'next/server';
131
132export async function POST(request: NextRequest) {
133    // Verify the Bearer token
134    const authHeader = request.headers.get('authorization');
135    const token = authHeader?.replace('Bearer ', '');
136
137    if (token !== process.env.OPENCOPY_WEBHOOK_SECRET) {
138        return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
139    }
140
141    const payload = await request.json();
142    const { event_type, data } = payload;
143
144    // Handle test events
145    if (event_type === 'test') {
146        return NextResponse.json({
147            success: true,
148            message: 'Webhook configured successfully'
149        });
150    }
151
152    // Handle article publish events
153    if (event_type === 'publish_article') {
154        const article = data.article;
155
156        // Create your blog post
157        const post = await prisma.post.create({
158            data: {
159                title: article.title,
160                slug: article.slug,
161                content: article.content_html,
162                excerpt: article.excerpt,
163                metaDescription: article.meta_description,
164                featuredImage: article.image_url,
165            },
166        });
167
168        return NextResponse.json({
169            id: post.id,
170            url: \`https://yourdomain.com/blog/\${post.slug}\`,
171        });
172    }
173
174    return NextResponse.json({ success: true });
175}`;function pt(){const e=$e.c(97),{auth:s}=ze().props,[a,x]=Ie.useState("php");let m;e[0]===Symbol.for("react.memo_cache_sentinel")?(m=t.jsx(Be,{title:"Webhook Integration Guide | OpenCopy.ai"}),e[0]=m):m=e[0];let r;e[1]===Symbol.for("react.memo_cache_sentinel")?(r=We(),e[1]=r):r=e[1];let i;e[2]===Symbol.for("react.memo_cache_sentinel")?(i=t.jsx(De,{className:"size-8"}),e[2]=i):i=e[2];let l;e[3]===Symbol.for("react.memo_cache_sentinel")?(l=t.jsxs(h,{href:r,className:"flex items-center gap-2",children:[i,t.jsxs("span",{className:"text-lg font-semibold text-slate-900 dark:text-white",children:["OpenCopy",t.jsx("span",{className:"text-[#00AAFF]",children:".ai"})]})]}),e[3]=l):l=e[3];let o;e[4]!==s.user?(o=t.jsx("header",{className:"border-b border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-950",children:t.jsxs("div",{className:"mx-auto flex h-16 max-w-5xl items-center justify-between px-6",children:[l,t.jsx("div",{className:"flex items-center gap-3",children:s.user?t.jsx(F,{asChild:!0,size:"sm",children:t.jsx(h,{href:Pe(),children:"Dashboard"})}):t.jsxs(t.Fragment,{children:[t.jsx(F,{variant:"ghost",asChild:!0,size:"sm",children:t.jsx(h,{href:qe(),children:"Log in"})}),t.jsx(F,{asChild:!0,size:"sm",className:"bg-[#00AAFF] hover:bg-[#0095e0]",children:t.jsx(h,{href:Le(),children:"Get Started"})})]})})]})}),e[4]=s.user,e[5]=o):o=e[5];let n;e[6]===Symbol.for("react.memo_cache_sentinel")?(n=t.jsx("div",{className:"border-b border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-950",children:t.jsxs("div",{className:"mx-auto max-w-5xl px-6 py-16",children:[t.jsx(Ue,{className:"mb-4 bg-[#00AAFF]/10 text-[#00AAFF] hover:bg-[#00AAFF]/20",children:"Developer Documentation"}),t.jsx("h1",{className:"mb-4 text-4xl font-bold tracking-tight text-slate-900 dark:text-white",children:"Webhook Integration Guide"}
175),t.jsx("p",{className:"max-w-2xl text-lg text-slate-600 dark:text-slate-400",children:"Automatically publish AI-generated articles to your website or CMS. OpenCopy sends structured JSON payloads to your endpoint whenever content is ready."})]})}),e[6]=n):n=e[6];let c;e[7]===Symbol.for("react.memo_cache_sentinel")?(c=t.jsxs("div",{className:"mb-16 grid gap-6 md:grid-cols-3",children:[t.jsx(He,{icon:Me,title:"Real-time Delivery",description:"Articles are sent to your endpoint immediately when published, with automatic retry on failures."}),t.jsx(He,{icon:Ye,title:"Secure by Default",description:"All webhooks require HTTPS and Bearer token authentication to protect your endpoint."}),t.jsx(He,{icon:Ke,title:"Flexible Format",description:"Receive content in both HTML and Markdown, plus SEO metadata, tags, and featured images."})]}),e[7]=c):c=e[7];let b;e[8]===Symbol.for("react.memo_cache_sentinel")?(b=t.jsx("h2",{className:"mb-6 text-2xl font-bold text-slate-900 dark:text-white",children:"Setting Up Your Webhook"}),e[8]=b):b=e[8];let d;e[9]===Symbol.for("react.memo_cache_sentinel")?(d=t.jsx("h3",{className:"mb-4 text-lg font-semibold text-slate-900 dark:text-white",children:"What You'll Need"}),e[9]=d):d=e[9];let p,C;e[10]===Symbol.for("react.memo_cache_sentinel")?(C=t.jsx("div",{className:"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[#00AAFF] text-sm font-bold text-white",children:"1"}),p=t.jsx("h4",{className:"font-medium text-slate-900 dark:text-white",children:"Webhook URL"}),e[10]=p,e[11]=C):(p=e[10],C=e[11]);let T;e[12]===Symbol.for("react.memo_cache_sentinel")?(T=t.jsxs("div",{className:"flex gap-4",children:[C,t.jsxs("div",{children:[p,t.jsxs("p",{className:"mt-1 text-sm text-slate-600 dark:text-slate-400",children:["A publicly accessible HTTPS endpoint that can receive POST requests. Example:"," ",t.jsx("code",{className:"rounded bg-slate-100 px-1.5 py-0.5 text-sm dark:bg-slate-800",children:"https://yoursite.com/api/webhook/opencopy"})]})]})]}),e[12]=T):T=e[12];let O,E;e[13]===Symbol.for("react.memo_cache_sentinel")?(O=t.jsx("div",{className:"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[#00AAFF] text-sm font-bold text-white",children:"2"}),E=t.jsx("h4",{className:"font-medium text-slate-900 dark:text-white",children:"Access Token"}),e[13]=O,e[14]=E):(O=e[13],E=e[14]);let R;e[15]===Symbol.for("react.memo_cache_sentinel")?(R=t.jsxs("section",{className:"mb-16",children:[b,t.jsxs("div",{className:"rounded-lg border border-slate-200 bg-white p-8 dark:border-slate-800 dark:bg-slate-900",children:[d,t.jsxs("div",{className:"space-y-6",children:[T,t.jsxs("div",{className:"flex gap-4",children:[O,t.jsxs("div",{children:[E,t.jsxs("p",{className:"mt-1 text-sm text-slate-600 dark:text-slate-400",children:["A secret token you generate to authenticate webhook requests. OpenCopy sends this as a Bearer token in the"," ",t.jsx("code",{className:"rounded bg-slate-100 px-1.5 py-0.5 text-sm dark:bg-slate-800",children:"Authorization"})," ","header. Generate a secure random string (32+ characters recommended)."]})]})]})]})]})]}),e[15]=R):R=e[15];let H,$;e[16]===Symbol.for("react.memo_cache_sentinel")?(H=t.jsx("h2",{className:"mb-6 text-2xl font-bold text-slate-900 dark:text-white",children:"Webhook Payload Structure"}),$=t.jsx("p",{className:"mb-6 text-slate-600 dark:text-slate-400",children:"When you publish an article from OpenCopy, we send a POST request to your webhook URL with the following JSON structure:"}),e[16]=H,e[17]=$):(H=e[16],$=e[17]);let P;e[18]===Symbol.for("react.memo_cache_sentinel")?(P=t.jsxs("div",{className:"mb-8",children:[t.jsx("h3",{className:"mb-3 text-sm font-semibold tracking-wide text-slate-500 uppercase dark:text-slate-400",children:"Publish Article Event"}),t.jsx(u,{code:Ze})]}),e[18]=P):P=e[18];let q;e[19]===Symbol.for("react.memo_cache_sentinel")?(q=t.jsx("h3",{className:"mb-4 text-lg font-semibold text-slate-900 dark:text-white",children:"Field Reference"}),e[19]=q):q=e[19];let L;e[20]===Symbol.for("react.memo_cache_sentinel")?(L=t.jsx("thead",{children:t.jsxs("tr",{className:"border-b border-slate-200 dark:border-slate-700",children:[t.jsx("th",{className:"pr-4 pb-3 text-left font-semibold text-slate-900 dark:text-white",children:"Field"}),t.jsx("th",{className:"pr-4 pb-3 text-left font-semibold text-slate-900 dark:text-white",children:"Type"}),t.jsx("th",{className:"pb-3 text-left font-semibold text-slate-900 dark:text-white",children:"Description"})]})}),e[20]=L):L=e[20];let I,z;e[21]===Symbol.for("react.memo_cache_sentinel")?(I=t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"event_type"}
175),z=t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"string"}),e[21]=I,e[22]=z):(I=e[21],z=e[22]);let B;e[23]===Symbol.for("react.memo_cache_sentinel")?(B=t.jsx("code",{className:"rounded bg-slate-100 px-1 dark:bg-slate-800",children:'"publish_article"'}),e[23]=B):B=e[23];let D;e[24]===Symbol.for("react.memo_cache_sentinel")?(D=t.jsxs("section",{className:"mb-16",children:[H,$,P,t.jsxs("div",{className:"rounded-lg border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900",children:[q,t.jsx("div",{className:"overflow-x-auto",children:t.jsxs("table",{className:"w-full text-sm",children:[L,t.jsxs("tbody",{className:"divide-y divide-slate-100 dark:divide-slate-800",children:[t.jsxs("tr",{children:[I,z,t.jsxs("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:[B," ","or"," ",t.jsx("code",{className:"rounded bg-slate-100 px-1 dark:bg-slate-800",children:'"test"'})]})]}),t.jsxs("tr",{children:[t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"timestamp"}),t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"string"}),t.jsx("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:"ISO 8601 formatted timestamp"})]}),t.jsxs("tr",{children:[t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"data.article.id"}),t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"integer"}),t.jsx("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:"Unique article ID in OpenCopy"})]}),t.jsxs("tr",{children:[t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"data.article.title"}),t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"string"}),t.jsx("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:"Article headline/title"})]}),t.jsxs("tr",{children:[t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"data.article.slug"}),t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"string"}),t.jsx("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:"URL-friendly slug for routing"})]}),t.jsxs("tr",{children:[t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"data.article.content_html"}),t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"string"}),t.jsx("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:"Full article content as HTML"})]}),t.jsxs("tr",{children:[t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"data.article.content_markdown"}),t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"string"}),t.jsx("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:"Full article content as Markdown"})]}),t.jsxs("tr",{children:[t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"data.article.meta_description"}),t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"string | null"}),t.jsx("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:"SEO meta description (150-160 chars)"})]}),t.jsxs("tr",{children:[t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"data.article.excerpt"}),t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"string | null"}),t.jsx("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:"Short summary for previews"})]}),t.jsxs("tr",{children:[t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"data.article.image_url"}),t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"string | null"}),t.jsx("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:"Featured image URL (absolute)"})]}),t.jsxs("tr",{children:[t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"data.article.tags"}),t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"string[]"}
175),t.jsx("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:"Array of tag/category names"})]}),t.jsxs("tr",{children:[t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"data.article.word_count"}),t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"integer"}),t.jsx("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:"Total word count"})]}),t.jsxs("tr",{children:[t.jsx("td",{className:"py-3 pr-4 font-mono text-xs text-[#00AAFF]",children:"data.article.reading_time_minutes"}),t.jsx("td",{className:"py-3 pr-4 text-slate-600 dark:text-slate-400",children:"integer"}),t.jsx("td",{className:"py-3 text-slate-600 dark:text-slate-400",children:"Estimated reading time"})]})]})]})})]})]}),e[24]=D):D=e[24];let U,W,M;e[25]===Symbol.for("react.memo_cache_sentinel")?(U=t.jsx("h2",{className:"mb-6 text-2xl font-bold text-slate-900 dark:text-white",children:"Test Connection Event"}),W=t.jsx("p",{className:"mb-6 text-slate-600 dark:text-slate-400",children:'When you click "Test Connection" in OpenCopy, we send a test payload to verify your endpoint is working correctly:'}),M=t.jsx(u,{code:Qe}),e[25]=U,e[26]=W,e[27]=M):(U=e[25],W=e[26],M=e[27]);let Y;e[28]===Symbol.for("react.memo_cache_sentinel")?(Y=t.jsx("strong",{children:"Note:"}),e[28]=Y):Y=e[28];let G;e[29]===Symbol.for("react.memo_cache_sentinel")?(G=t.jsx("code",{className:"rounded bg-amber-100 px-1 dark:bg-amber-900",children:'event_type: "test"'}),e[29]=G):G=e[29];let V;e[30]===Symbol.for("react.memo_cache_sentinel")?(V=t.jsxs("section",{className:"mb-16",children:[U,W,M,t.jsx("div",{className:"mt-4 rounded-lg border border-amber-200 bg-amber-50 p-4 dark:border-amber-900 dark:bg-amber-950/50",children:t.jsxs("p",{className:"text-sm text-amber-800 dark:text-amber-200",children:[Y," Test events have"," ",G," ","and"," ",t.jsx("code",{className:"rounded bg-amber-100 px-1 dark:bg-amber-900",children:"id: 0"}),". Your endpoint should handle these gracefully without creating actual content."]})})]}),e[30]=V):V=e[30];let J,X;e[31]===Symbol.for("react.memo_cache_sentinel")?(J=t.jsx("h2",{className:"mb-6 text-2xl font-bold text-slate-900 dark:text-white",children:"Expected Response"}),X=t.jsx("p",{className:"mb-6 text-slate-600 dark:text-slate-400",children:"Your endpoint should return a JSON response. OpenCopy looks for specific fields to track the publication:"}),e[31]=J,e[32]=X):(J=e[31],X=e[32]);let K;e[33]===Symbol.for("react.memo_cache_sentinel")?(K=t.jsxs("section",{className:"mb-16",children:[J,X,t.jsxs("div",{className:"grid gap-6 md:grid-cols-2",children:[t.jsxs("div",{children:[t.jsx("h3",{className:"mb-3 text-sm font-semibold tracking-wide text-green-600 uppercase dark:text-green-400",children:"Success Response (2xx)"}),t.jsx(u,{code:`{
176  "id": "123",
177  "url": "https://yoursite.com/blog/article-slug"
178}`}),t.jsx("p",{className:"mt-3 text-sm text-slate-600 dark:text-slate-400",children:"Return the created post's ID and public URL. These are stored in OpenCopy for your reference."})]}),t.jsxs("div",{children:[t.jsx("h3",{className:"mb-3 text-sm font-semibold tracking-wide text-red-600 uppercase dark:text-red-400",children:"Error Response (4xx/5xx)"}),t.jsx(u,{code:`{
179  "error": "Invalid article data",
180  "message": "Title is required"
181}`}),t.jsx("p",{className:"mt-3 text-sm text-slate-600 dark:text-slate-400",children:"Return an error message. OpenCopy will retry on 5xx errors up to 3 times."})]})]})]}),e[33]=K):K=e[33];let Z,Q;e[34]===Symbol.for("react.memo_cache_sentinel")?(Z=t.jsx("h2",{className:"mb-6 text-2xl font-bold text-slate-900 dark:text-white",children:"Request Headers"}),Q=t.jsx("p",{className:"mb-6 text-slate-600 dark:text-slate-400",children:"OpenCopy sends the following headers with every webhook request:"}),e[34]=Z,e[35]=Q):(Z=e[34],Q=e[35]);let ee;e[36]===Symbol.for("react.memo_cache_sentinel")?(ee=t.jsx("thead",{className:"bg-slate-50 dark:bg-slate-900",children:t.jsxs("tr",{children:[t.jsx("th",{className:"px-4 py-3 text-left font-semibold text-slate-900 dark:text-white",children:"Header"}),t.jsx("th",{className:"px-4 py-3 text-left font-semibold text-slate-900 dark:text-white",children:"Value"})]})}),e[36]=ee):ee=e[36];let te;
181e[37]===Symbol.for("react.memo_cache_sentinel")?(te=t.jsx("td",{className:"px-4 py-3 font-mono text-xs text-[#00AAFF]",children:"Authorization"}),e[37]=te):te=e[37];let se,ae;e[38]===Symbol.for("react.memo_cache_sentinel")?(se=t.jsxs("tr",{children:[te,t.jsx("td",{className:"px-4 py-3 text-slate-600 dark:text-slate-400",children:t.jsx("code",{className:"rounded bg-slate-100 px-1.5 py-0.5 dark:bg-slate-800",children:"Bearer your-access-token"})})]}),ae=t.jsx("td",{className:"px-4 py-3 font-mono text-xs text-[#00AAFF]",children:"Content-Type"}),e[38]=se,e[39]=ae):(se=e[38],ae=e[39]);let le,re;e[40]===Symbol.for("react.memo_cache_sentinel")?(le=t.jsxs("tr",{children:[ae,t.jsx("td",{className:"px-4 py-3 text-slate-600 dark:text-slate-400",children:t.jsx("code",{className:"rounded bg-slate-100 px-1.5 py-0.5 dark:bg-slate-800",children:"application/json"})})]}),re=t.jsx("td",{className:"px-4 py-3 font-mono text-xs text-[#00AAFF]",children:"Accept"}),e[40]=le,e[41]=re):(le=e[40],re=e[41]);let oe,ie;e[42]===Symbol.for("react.memo_cache_sentinel")?(oe=t.jsxs("tr",{children:[re,t.jsx("td",{className:"px-4 py-3 text-slate-600 dark:text-slate-400",children:t.jsx("code",{className:"rounded bg-slate-100 px-1.5 py-0.5 dark:bg-slate-800",children:"application/json"})})]}),ie=t.jsx("td",{className:"px-4 py-3 font-mono text-xs text-[#00AAFF]",children:"User-Agent"}),e[42]=oe,e[43]=ie):(oe=e[42],ie=e[43]);let ne;e[44]===Symbol.for("react.memo_cache_sentinel")?(ne=t.jsxs("section",{className:"mb-16",children:[Z,Q,t.jsx("div",{className:"overflow-hidden rounded-lg border border-slate-200 dark:border-slate-800",children:t.jsxs("table",{className:"w-full text-sm",children:[ee,t.jsxs("tbody",{className:"divide-y divide-slate-200 bg-white dark:divide-slate-800 dark:bg-slate-950",children:[se,le,oe,t.jsxs("tr",{children:[ie,t.jsx("td",{className:"px-4 py-3 text-slate-600 dark:text-slate-400",children:t.jsx("code",{className:"rounded bg-slate-100 px-1.5 py-0.5 dark:bg-slate-800",children:"OpenCopy/1.0"})})]})]})]})})]}),e[44]=ne):ne=e[44];let ce,de;e[45]===Symbol.for("react.memo_cache_sentinel")?(ce=t.jsx("h2",{className:"mb-6 text-2xl font-bold text-slate-900 dark:text-white",children:"Implementation Examples"}),de=t.jsx("p",{className:"mb-6 text-slate-600 dark:text-slate-400",children:"Here are example webhook handlers for popular frameworks:"}),e[45]=ce,e[46]=de):(ce=e[45],de=e[46]);let xe;e[47]===Symbol.for("react.memo_cache_sentinel")?(xe=()=>x("php"),e[47]=xe):xe=e[47];const Oe=`rounded-lg px-4 py-2 text-sm font-medium transition-colors ${a==="php"?"bg-[#00AAFF] text-white":"bg-slate-100 text-slate-700 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-700"}`;let f;e[48]!==Oe?(f=t.jsx("button",{onClick:xe,className:Oe,children:"PHP / Laravel"}),e[48]=Oe,e[49]=f):f=e[49];let me;e[50]===Symbol.for("react.memo_cache_sentinel")?(me=()=>x("node"),e[50]=me):me=e[50];const Ee=`rounded-lg px-4 py-2 text-sm font-medium transition-colors ${a==="node"?"bg-[#00AAFF] text-white":"bg-slate-100 text-slate-700 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-700"}`;let g;e[51]!==Ee?(g=t.jsx("button",{onClick:me,className:Ee,children:"Node.js / Express"}),e[51]=Ee,e[52]=g):g=e[52];let he;e[53]===Symbol.for("react.memo_cache_sentinel")?(he=()=>x("nextjs"),e[53]=he):he=e[53];const Re=`rounded-lg px-4 py-2 text-sm font-medium transition-colors ${a==="nextjs"?"bg-[#00AAFF] text-white":"bg-slate-100 text-slate-700 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-700"}`;let j;e[54]!==Re?(j=t.jsx("button",{onClick:he,className:Re,children:"Next.js"}),e[54]=Re,e[55]=j):j=e[55];let y;e[56]!==f||e[57]!==g||e[58]!==j?(y=t.jsxs("div",{className:"mb-4 flex gap-2",children:[f,g,j]}),e[56]=f,e[57]=g,e[58]=j,e[59]=y):y=e[59];let k;e[60]!==a?(k=a==="php"&&t.jsx(u,{code:et,language:"php"}),e[60]=a,e[61]=k):k=e[61];let N;e[62]!==a?(N=a==="node"&&t.jsx(u,{code:tt,language:"javascript"}),e[62]=a,e[63]=N):N=e[63];let _;e[64]!==a?(_=a==="nextjs"&&t.jsx(u,{code:st,language:"typescript"}),e[64]=a,e[65]=_):_=e[65];let v;e[66]!==k||e[67]!==N||e[68]!==_?(v=t.jsxs("div",{children:[k,N,_]}),e[66]=k,e[67]=N,e[68]=_,e[69]=v):v=e[69];let w;e[70]!==y||e[71]!==v?(w=t.jsxs("section",{className:"mb-16",children:[ce,de,y,v]}),e[70]=y,e[71]=v,e[72]=w):w=e[72];let pe;e[73]===Symbol.for("react.memo_cache_sentinel")?(pe=t.jsx("h2",{className:"mb-6 text-2xl font-bold text-slate-900 dark:text-white",children:"Security Best Practices"}),e[73]=pe):pe=e[73];let be;e[74]===Symbol.for("react.memo_cache_sentinel")?(be=t.jsxs("div",{className:"rounded-lg border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900",children:[t.jsx("h3",{className:"mb-2 font-semibold text-slate-900 dark:text-white",children:"Always Verify the Access Token"}
181),t.jsx("p",{className:"text-sm text-slate-600 dark:text-slate-400",children:"Check that the Bearer token in the Authorization header matches your configured secret. Reject requests with invalid or missing tokens with a 401 response."})]}),e[74]=be):be=e[74];let ue;e[75]===Symbol.for("react.memo_cache_sentinel")?(ue=t.jsxs("div",{className:"rounded-lg border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900",children:[t.jsx("h3",{className:"mb-2 font-semibold text-slate-900 dark:text-white",children:"Use HTTPS Only"}),t.jsx("p",{className:"text-sm text-slate-600 dark:text-slate-400",children:"OpenCopy requires HTTPS endpoints. Never use HTTP as it exposes your access token and content in transit."})]}),e[75]=ue):ue=e[75];let fe;e[76]===Symbol.for("react.memo_cache_sentinel")?(fe=t.jsx("h3",{className:"mb-2 font-semibold text-slate-900 dark:text-white",children:"Generate Strong Access Tokens"}),e[76]=fe):fe=e[76];let ge;e[77]===Symbol.for("react.memo_cache_sentinel")?(ge=t.jsxs("div",{className:"rounded-lg border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900",children:[fe,t.jsxs("p",{className:"text-sm text-slate-600 dark:text-slate-400",children:["Use cryptographically secure random strings of at least 32 characters. Tools like"," ",t.jsx("code",{className:"rounded bg-slate-100 px-1 dark:bg-slate-800",children:"openssl rand -hex 32"})," ","work great."]})]}),e[77]=ge):ge=e[77];let je;e[78]===Symbol.for("react.memo_cache_sentinel")?(je=t.jsxs("section",{className:"mb-16",children:[pe,t.jsxs("div",{className:"space-y-4",children:[be,ue,ge,t.jsxs("div",{className:"rounded-lg border border-slate-200 bg-white p-6 dark:border-slate-800 dark:bg-slate-900",children:[t.jsx("h3",{className:"mb-2 font-semibold text-slate-900 dark:text-white",children:"Sanitize HTML Content"}),t.jsx("p",{className:"text-sm text-slate-600 dark:text-slate-400",children:"If you render the HTML content directly, ensure you sanitize it to prevent XSS attacks. Use libraries like DOMPurify (JavaScript) or HTMLPurifier (PHP)."})]})]})]}),e[78]=je):je=e[78];let ye;e[79]===Symbol.for("react.memo_cache_sentinel")?(ye=t.jsx("h2",{className:"mb-6 text-2xl font-bold text-slate-900 dark:text-white",children:"Troubleshooting"}),e[79]=ye):ye=e[79];let ke,Ne,_e,ve;e[80]===Symbol.for("react.memo_cache_sentinel")?(ke=t.jsxs("div",{children:[t.jsx("h3",{className:"mb-2 font-semibold text-slate-900 dark:text-white",children:"Connection Timeout"}),t.jsx("p",{className:"text-sm text-slate-600 dark:text-slate-400",children:"By default, OpenCopy waits 30 seconds for a response. If your processing takes longer, consider accepting the webhook quickly and processing asynchronously (e.g., using a job queue)."})]}),Ne=t.jsxs("div",{children:[t.jsx("h3",{className:"mb-2 font-semibold text-slate-900 dark:text-white",children:"401 Unauthorized Errors"}),t.jsx("p",{className:"text-sm text-slate-600 dark:text-slate-400",children:"Ensure the access token configured in OpenCopy matches exactly what your endpoint expects. Check for trailing spaces or newlines."})]}),_e=t.jsxs("div",{children:[t.jsx("h3",{className:"mb-2 font-semibold text-slate-900 dark:text-white",children:"SSL Certificate Errors"}),t.jsx("p",{className:"text-sm text-slate-600 dark:text-slate-400",children:"Make sure your SSL certificate is valid and not self-signed. Free certificates from Let's Encrypt work perfectly."})]}),ve=t.jsx("h3",{className:"mb-2 font-semibold text-slate-900 dark:text-white",children:"Retries and Duplicate Content"}),e[80]=ke,e[81]=Ne,e[82]=_e,e[83]=ve):(ke=e[80],Ne=e[81],_e=e[82],ve=e[83]);let we;e[84]===Symbol.for("react.memo_cache_sentinel")?(we=t.jsxs("section",{className:"mb-16",children:[ye,t.jsxs("div",{className:"space-y-6",children:[ke,Ne,_e,t.jsxs("div",{children:[ve,t.jsxs("p",{className:"text-sm text-slate-600 dark:text-slate-400",children:["OpenCopy retries failed requests (5xx errors) up to 3 times. Implement idempotency using the",t.jsx("code",{className:"mx-1 rounded bg-slate-100 px-1 dark:bg-slate-800",children:"data.article.id"}),"field to prevent duplicate posts."]})]})]})]}),e[84]=we):we=e[84];let Se,Ae;e[85]===Symbol.for("react.memo_cache_sentinel")?(Se=t.jsx("h2",{className:"mb-4 text-2xl font-bold",children:"Ready to Get Started?"}),Ae=t.jsx("p",{className:"mb-6 text-blue-100",children:"Set up your webhook integration in minutes and start publishing AI-generated content automatically."}),e[85]=Se,e[86]=Ae):(Se=e[85],Ae=e[86]);let S;e[87]!==s.user?(S=t.jsxs("section",{className:"rounded-2xl bg-gradient-to-br from-[#00AAFF] to-[#394f87] p-8 text-center text-white",children:[Se,Ae,t.jsx("div",{className:"flex justify-center gap-4",children:s.user?t.jsx(F,{asChild:!0,size:"lg",className:"bg-white text-[#00AAFF] hover:bg-slate-100",children:t.jsx(h,{href:Pe(),children:"Go to Dashboard"})}):t.jsxs(t.Fragment,{children:[t.jsx(F,{asChild:!0,size:"lg",className:"bg-white text-[#00AAFF] hover:bg-slate-100",children:t.jsx(h,{href:Le(),children:"Start Free Trial"})}),t.jsx(F,{asChild:!0,size:"lg",className:"border-2 border-white bg-transparent text-white hover:bg-white/10",children:t.jsx(h,{href:qe(),children:"Log In"})})]})})]}),e[87]=s.user,e[88]=S):S=e[88];let A;e[89]!==w||e[90]!==S?(A=t.jsxs("main",{className:"mx-auto max-w-5xl px-6 py-12",children:[c,R,D,V,K,ne,w,je,we,S]}),e[89]=w,e[90]=S,e[91]=A):A=e[91];let Fe;e[92]===Symbol.for("react.memo_cache_sentinel")?(Fe=t.jsxs("p",{children:["© ",new Date().getFullYear()," OpenCopy.ai. All rights reserved."]}),e[92]=Fe):Fe=e[92];let Ce;e[93]===Symbol.for("react.memo_cache_sentinel")?(Ce=t.jsx("footer",{className:"border-t border-slate-200 py-8 dark:border-slate-800",children:t.jsxs("div",{className:"mx-auto max-w-5xl px-6 text-center text-sm text-slate-500 dark:text-slate-400",children:[Fe,t.jsxs("div",{className:"mt-2 flex justify-center gap-4",children:[t.jsx(h,{href:"/terms",className:"hover:text-slate-900 dark:hover:text-white",children:"Terms of Service"}),t.jsx(h,{href:"/privacy",className:"hover:text-slate-900 dark:hover:text-white",children:"Privacy Policy"}),t.jsx(h,{href:"/docs/webhook-integration",className:"text-[#00AAFF]",children:"Webhook Docs"})]})]})}),e[93]=Ce):Ce=e[93];let Te;return e[94]!==o||e[95]!==A?(Te=t.jsxs(t.Fragment,{children:[m,t.jsxs("div",{className:"min-h-screen bg-slate-50 dark:bg-slate-950",children:[o,n,A,Ce]})]}),e[94]=o,e[95]=A,e[96]=Te):Te=e[96],Te}export{pt as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.