> ## Documentation Index
> Fetch the complete documentation index at: https://www.ayrshare.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Link Completion Events

> उपयोगकर्ता के अकाउंट कनेक्ट करते ही सूचित हों, उसके लिए poll करने के बजाय।

export const PlansAvailable = ({plans = [], maxPackRequired}) => {
  let displayPlans = plans;
  if (plans && plans.length === 1) {
    const lowerCasePlan = plans[0].toLowerCase();
    if (lowerCasePlan === "business") {
      displayPlans = ["Launch", "Business", "Enterprise"];
    } else if (lowerCasePlan === "premium") {
      displayPlans = ["Premium", "Launch", "Business", "Enterprise"];
    }
  }
  return <Note>
Available on {displayPlans.length === 1 ? "the " : ""}
{displayPlans.join(", ").replace(/\b\w/g, l => l.toUpperCase())}{" "}
{displayPlans.length > 1 ? "plans" : "plan"}.

{maxPackRequired && <span onClick={() => window.open('https://www.ayrshare.com/docs/additional/maxpack', '_self')} className="flex items-center mt-2 cursor-pointer">
 <span className="px-1.5 py-0.5 rounded text-sm" style={{
    backgroundColor: '#C264B6',
    color: 'white',
    fontSize: '12px'
  }}>
   Max Pack required
 </span>
</span>}
</Note>;
};

<PlansAvailable plans={["business"]} maxPackRequired={false} />

जब आप किसी लिंकिंग पेज को पॉपअप में खोलते हैं, तो आपका अपना पेज सुन सकता है कि उसमें क्या होता
है: आपके उपयोगकर्ता ने Reddit कनेक्ट किया, वे पीछे हट गए, कनेक्शन विफल हुआ। आपको प्रति परिणाम एक
event मिलता है, इसलिए आपका UI किसी timer पर नहीं, बल्कि घटित होते ही अपडेट होता है।

लिंक बनाते समय [`origin`](/docs/apis/profiles/create-link-session) सेट करें, लौटाया गया `url` एक पॉपअप
में खोलें, और सुनें। और कुछ आवश्यक नहीं है, और बिना `origin` के बनाए गए लिंक्स के लिए कुछ नहीं
बदलता — वे बिल्कुल वैसे ही व्यवहार करते हैं जैसे हमेशा करते आए हैं।

<Note>
  **[एम्बेडेड विजेट](/docs/multiple-users/connect-widget) उपयोग कर रहे हैं? यह आपके लिए पहले से wired
  है।** Script ये events प्राप्त करती है और `connect:` prefix हटाकर उन्हें
  `connect.on("success", …)` को सौंप देती है — लिखने के लिए कोई `message` listener नहीं, कोई
  origin जाँच नहीं, कोई `popup.closed` poll नहीं। यह पेज उसके नीचे का wire protocol है, और वह
  जिसके विरुद्ध आप तब बनाते हैं जब विंडो के मालिक **आप** हों: डायरेक्ट मोड, या आपका स्वयं खोला
  हुआ पॉपअप।
</Note>

<Note>
  Events केवल उसी सटीक `origin` को भेजे जाते हैं जो आपने लिंक पर सेट किया, और केवल उस विंडो को
  जिसने पॉपअप खोला। फिर भी अपने listener में हमेशा `event.origin` जाँचें: कोई भी पेज आपकी विंडो
  को message पोस्ट कर सकता है, और origin ही message का एकमात्र हिस्सा है जिसे जाली नहीं बनाया
  जा सकता।
</Note>

## Events

आपके पेज पर पोस्ट किया गया हर message `{ source: "ayrshare", version: 1, event, ... }` आकार का
एक ऑब्जेक्ट है, और जब भी event किसी नेटवर्क के बारे में हो तो उसमें `network` होता है। दो events
ऐसे नहीं हैं: होस्टेड लिंकिंग पेज से आने वाला `connect:closed`, जहाँ इसका अर्थ है कि आपके
उपयोगकर्ता ने Done दबाया, न कि किसी एक कनेक्शन का समाप्त होना, और विजेट का `connect:ready`
(नीचे देखें)। जो परिणाम आपका अपना कोड synthesize करता है — ब्लॉक हुआ पॉपअप, या आपके उपयोगकर्ता
द्वारा बंद की गई विंडो — हमसे नहीं आते और उनमें केवल वही होता है जो आप उन्हें देते हैं।

<Note>
  [एम्बेडेड विजेट](/docs/multiple-users/connect-widget) एक event पर भिन्न है। उसका `ready` किसी नेटवर्क
  के बारे में कुछ कहने के बजाय यह घोषित करता है कि कोई slot तैयार है, इसलिए उसमें कोई `network`
  नहीं होता — जबकि पॉपअप का `ready` उस नेटवर्क का नाम बताता है जिसके लिए वह खोला गया। यदि आप
  दोनों सरफ़ेस एक ही listener से संभालते हैं, तो `ready` पर `network` को defensive तरीक़े से
  पढ़ें।

  विजेट एक ऐसा `cancelled` reason भी जोड़ता है जो यह सरफ़ेस कभी नहीं भेजता: `superseded`, जब
  दूसरी `popup()` कॉल किसी अभी चल रहे प्रयास को प्रतिस्थापित करती है। यहाँ एक विंडो और एक परिणाम
  है, इसलिए प्रतिस्थापित करने के लिए कुछ नहीं है।
</Note>

| Event | अतिरिक्त फ़ील्ड | कब भेजा जाता है |
| - | - | - |
| `connect:ready` | | पेज लोड हो चुका है और लिंक जाँचा जा चुका है। |
| `connect:started` | | आपका उपयोगकर्ता सोशल नेटवर्क पर भेजा जा चुका है। |
| `connect:selection` | `step` | स्क्रीन पर कोई picker या फ़ॉर्म है — आपके उपयोगकर्ता को कुछ करना है। |
| `connect:success` | `refId`, `displayName` | अकाउंट कनेक्टेड **और सेव** है। `refId` वह User Profile है जिससे वह कनेक्ट हुआ। `displayName` अकाउंट का नाम है, और जब हमारे पास अभी न हो तो छोड़ दिया जाता है। |
| `connect:error` | `message`, और `code` जब कोई हो | कनेक्शन विफल हुआ। `code` [त्रुटि संदर्भ](/docs/errors/overview) से मेल खाता है; जब विफलता का कोई catalogued code न हो, और आपके अपने snippet द्वारा synthesize किए गए किसी भी परिणाम पर — जैसे ब्लॉक हुआ पॉपअप — यह अनुपस्थित होता है। |
| `connect:cancelled` | `reason` | आपका उपयोगकर्ता पीछे हट गया। `reason` `popupClosed`, `scopesDenied`, या `userCancelled` है। |
| `connect:closed` | | पॉपअप स्वयं बंद होने वाला है। होस्टेड लिंकिंग पेज से आने पर इसमें कोई `network` नहीं होता, जहाँ इसका अर्थ है कि आपके उपयोगकर्ता ने Done दबाया, न कि किसी एक कनेक्शन का समाप्त होना। |

प्रति कनेक्शन `connect:success`, `connect:error` या `connect:cancelled` में से ठीक एक आता है।
`connect:closed` उनमें से नहीं है — वह बाद में आता है, यह बताने के लिए कि पॉपअप जानबूझकर बंद
हुआ।

`connect:success` केवल अकाउंट सेव हो जाने के बाद भेजा जाता है, इसलिए उसके तुरंत बाद
[`GET /user`](/docs/apis/user/profile-details) कनेक्टेड अकाउंट को पहले से दिखाता है।

<Note>
  `connect:error` के बाद पॉपअप खुला रहता है ताकि आपका उपयोगकर्ता पढ़ सके कि क्या ग़लत हुआ।
  `connect:success` और `connect:cancelled` के बाद वह स्वयं बंद हो जाता है। debug करते समय हर
  स्थिति में उसे खुला रखने के लिए URL में `&autoClose=false` जोड़ें।
</Note>

## सुनना

दो चीज़ें जो यह snippet करता है और जिन्हें छोड़ देना आसान है। यह `event.origin` जाँचता है, और
आपके उपयोगकर्ता द्वारा हाथ से बंद किए गए पॉपअप पर नज़र रखता है — बंद हुई विंडो कुछ नहीं भेज
सकती, इसलिए poll करना ही इसे नोटिस करने का एकमात्र तरीक़ा है।

```javascript theme={"system"}
function connectAccount(url) {
  // Derive the origin from the URL you were given rather than hard-coding one:
  // if your account uses its own linking domain, the popup runs on that.
  const popupOrigin = new URL(url).origin;

  const popup = window.open(url, "ayrshare-connect", "width=600,height=800");
  if (!popup) {
    handleOutcome({ event: "connect:error", message: "The popup was blocked." });
    return;
  }

  // Declared before anything can call `cleanup`: a message arriving early would
  // otherwise hit `poll` in its temporal dead zone and throw.
  let poll;

  const cleanup = () => {
    clearInterval(poll);
    window.removeEventListener("message", onMessage);
  };

  const onMessage = event => {
    // Both checks, not just the origin: another tab or frame on the same origin
    // could otherwise post a message your handler would believe.
    if (event.origin !== popupOrigin || event.source !== popup) return;
    const message = event.data;
    if (!message || message.source !== "ayrshare") return;

    if (["connect:success", "connect:error", "connect:cancelled"].includes(message.event)) {
      // `finally`, so your own handler throwing cannot leave the poll running —
      // it would later see the closed popup and report `cancelled` on top of the
      // outcome you already had. Cleanup also matters after `connect:error`,
      // where the popup stays open so your user can read it.
      try {
        handleOutcome(message);
      } finally {
        cleanup();
      }
    }
  };
  window.addEventListener("message", onMessage);

  // A hand-closed popup sends nothing, so watch for it. Wait a moment before
  // deciding: the popup closes itself right after sending, and the message can
  // still be in flight when you first see the window go.
  let closedAt = null;
  poll = setInterval(() => {
    if (!popup.closed) return;
    if (closedAt === null) {
      closedAt = Date.now();
      return;
    }
    if (Date.now() - closedAt < 750) return;

    cleanup();
    handleOutcome({ event: "connect:cancelled", reason: "popupClosed" });
  }, 500);
}
```

## त्रुटियाँ

`connect:error` वही codes ले जाता है जो बाक़ी API में हैं, इसलिए यहाँ दिखने वाले code का वही अर्थ
है जो हर जगह है। इस सरफ़ेस के लिए विशिष्ट एकमात्र:

| Code | अर्थ |
| - | - |
| `513` | लिंक single-network connect विंडो के रूप में खोला गया, लेकिन उसके लिए बनाया नहीं गया था। केवल तभी पहुँचा जा सकता है जब आप वह URL स्वयं बनाएँ — यह एंडपॉइंट जो `url` लौटाता है वह हमेशा उसके बनाए लिंक से मेल खाता है। |

बाक़ी कुछ भी सोशल नेटवर्क की अपनी विफलता है, जो उस विफलता के पहले से मौजूद code के साथ रिपोर्ट
होती है — उदाहरण के लिए Instagram प्राधिकरण समस्या के लिए `322`, जिसमें ऐसा अकाउंट भी शामिल है
जो अभी Professional के बजाय Personal है।

### मृत लिंक अलग तरीक़े से आता है

जो लिंक **expired**, **revoked** या **unknown** है वह पेज के यह जान पाने से पहले ही ठुकरा दिया
जाता है कि events कहाँ भेजने हैं, इसलिए वह कोई भेज नहीं सकता। आपका उपयोगकर्ता स्क्रीन पर कारण और
उसका code देखता है, और विंडो बंद करने पर आपका पेज `connect:cancelled` सुनता है।

उन्हें अलग-अलग पहचानने के लिए, [Link Session प्राप्त करें](/docs/apis/profiles/get-link-session) को
poll करें: यह `expired` और `revoked` को प्रामाणिक रूप से रिपोर्ट करता है, और जो लिंक मौजूद नहीं
है उसके लिए `502` लौटाता है।

## यदि आप पॉपअप प्रबंधित नहीं करना चाहें

दो विकल्प, और केवल दूसरा events छोड़ता है।

**विंडो का स्वामित्व विजेट को दें।** [एम्बेडेड विजेट](/docs/multiple-users/connect-widget) उसे आपके लिए
खोलता और देखता है और ऊपर का हर event आपके handlers तक पहुँचाता है। आपको अब भी अकाउंट सेव होते
ही `success` मिलता है; आप बस plumbing नहीं लिखते। उसके फ़्रेमों का यह भी अर्थ है कि अधिकांश
नेटवर्क नेटवर्क के अपने लॉगिन तक कोई पॉपअप ही नहीं खोलते।

**इसके बजाय poll करें।** यदि पॉपअप वाक़ई उपलब्ध नहीं है — कोई server-rendered ऐप, या सिस्टम
ब्राउज़र में लिंक खोलने वाला मोबाइल ऐप — तो
[Link Session प्राप्त करें](/docs/apis/profiles/get-link-session) को poll करें। यह अकाउंट सेव होते ही
`completedAt` और `completedNetworks` रिपोर्ट करता है, जो वही क्षण है जब `connect:success` भेजा
गया होता। Telegram हमेशा इसी तरह पूरा होता है, क्योंकि वह बिना किसी ब्राउज़र callback के out of
band पूरा होता है।


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.