एंडपॉइंट
`webhooks->list`, `listAll`, `iterate`, `get`, `create`, `update`, `delete`, `rotateSecret`, `test`, `getDelivery` और `replayDelivery`, और डिलीवरी तथा गतिविधि लॉग।
हर मेथड
use OpenEmail\Constants\WebhookEvents; $endpoint = $client->webhooks->create([ 'url' => 'https://acme.com/hooks/mail', 'eventTypes' => [WebhookEvents::EMAIL_SENT, WebhookEvents::EMAIL_BOUNCED], 'description' => 'Billing service',]); file_put_contents('.openemail-webhook-secret', $endpoint['secret']); $client->webhooks->list();$client->webhooks->get($endpoint['id']);$client->webhooks->update($endpoint['id'], ['enabled' => false]);$client->webhooks->test($endpoint['id']); foreach ($client->webhooks->listDeliveries($endpoint['id'], limit: 1) as $latest) { $client->webhooks->getDelivery($endpoint['id'], $latest['id']); $client->webhooks->replayDelivery($endpoint['id'], $latest['id']);} $rotated = $client->webhooks->rotateSecret($endpoint['id']);file_put_contents('.openemail-webhook-secret', $rotated['secret']); $client->webhooks->delete($endpoint['id']);rotateSecret को छोड़कर create ही अकेली बार है जब secret लौटाया जाता है। कोई read उसे कभी नहीं दोहराता, इसलिए बाकी कुछ भी करने से पहले उसे संग्रहीत करें। डिफ़ॉल्ट सेट के लिए eventTypes छोड़ दें, यानी email.replied को छोड़कर हर email.* event। email.replied, domain.*, suppression.*, file.* और form.* किसी endpoint तक तभी पहुँचते हैं जब वह उनका नाम ले।
list एक OpenEmail\Result\Page लौटाता है, listAll हर endpoint एक array में लौटाता है, और iterate एक Generator लौटाता है जो एक बार में एक endpoint yield करता है। create और update बॉडी को API के नामों वाले एक array के रूप में लेते हैं, और हर endpoint camelCase कुंजियों वाले array के रूप में लौटता है।
rotateSecret में कोई overlap विंडो नहीं है। पुराना secret तुरंत काम करना बंद कर देता है, इसलिए rotate करने से पहले नया तैनात करें। इसे कभी अपने आप retry नहीं किया जाता: retry दूसरी बार rotate कर देता और उस secret को रद्द कर देता जो पहली कोशिश ने लौटाया था।
create पर भी पुनः प्रयास नहीं होता, इसलिए नेटवर्क विफलता ऐसा endpoint बना छोड़ सकती है जिसका secret आपने कभी देखा ही नहीं। दोबारा बनाने से पहले list जाँचें। एक वर्कस्पेस में डिफ़ॉल्ट रूप से 10 endpoints होते हैं, और सीमा के बाद अगला 422 workspace_limit_reached है।
आप किसकी सदस्यता ले सकते हैं
OpenEmail\Constants\WebhookEvents हर event का नाम एक constant के रूप में देता है, और WebhookEvents::values() उनकी सूची देता है, इसलिए आप बिना रिक्वेस्ट के सूची दिखा सकते हैं। webhooks->listEvents वही नाम हर एक के लेबल के साथ लौटाता है, साथ में वे सीमाएँ जो endpoint पर लागू होती हैं, maxEndpoints, maxAddresses और maxDomains में। events मेलबॉक्स के events हैं, इस API के नहीं: email.received ऐप में आने वाली मेल पर चलता है, और email.sent composer द्वारा भेजे गए संदेश पर। subscribe करना अपने API ट्रैफ़िक पर नज़र रखने जैसा नहीं है।
file.uploaded तब चलता है जब कोई फ़ाइल Files पेज पर रखी जाती है, और file.deleted जब कोई हटाई जाती है। इनके data में fileId, filename, mimeType, sizeBytes, direction, to, threadId, messageId, और uploadedAt या deletedAt होते हैं। to वह पता है जिसकी फ़ाइल है, या पूरे वर्कस्पेस की फ़ाइल के लिए null।
फ़ाइल events डिफ़ॉल्ट सेट में नहीं हैं, इसलिए कोई endpoint इन्हें तभी पाता है जब वह eventTypes में इनका नाम ले। कुछ पतों तक सीमित endpoint सिर्फ़ उन्हीं पतों की फ़ाइलों के बारे में सुनता है, इसलिए पूरे वर्कस्पेस के लिए किया गया अपलोड, जिसमें to null है, उसे नहीं भेजा जाता।
form.submitted तब चलता है जब कोई आपके किसी फ़ॉर्म से साइन अप करता है, और form.confirmed तब जब कोई लंबित साइन-अप ऑडियंस में जुड़ता है, क्योंकि व्यक्ति ने पुष्टि लिंक खोला या आपने उसे मंज़ूरी दी। form.submitted के data में formId, formName, submissionId, email, status, answers, audienceIds, sourceUrl और submittedAt होते हैं। form.confirmed के data में formId, formName, submissionId, email, audienceIds, via, जो link या approval है, और confirmedAt होते हैं।
डबल ऑप्ट-इन के बिना वाले फ़ॉर्म पर साइन-अप status added के साथ form.submitted भेजता है और कोई form.confirmed नहीं, इसलिए उसी को वह क्षण मानें जब कोई जुड़ता है। पुष्टि से पहले फिर से साइन-अप करने वाले का submissionId वही रहता है, और form.submitted दोबारा तभी भेजा जाता है जब उसके जवाब बदले हों। फ़ॉर्म events डिफ़ॉल्ट सेट में नहीं हैं, और कुछ पतों तक सीमित endpoint इन्हें कभी नहीं पाता, क्योंकि साइन-अप पूरे वर्कस्पेस के होते हैं।
यह साबित करना कि यह काम करता है
$result = $client->webhooks->test('whe_3f9c2a7b1e4d8f60a5c7b92d');echo $result['delivery']['status'], ' ', $result['delivery']['responseCode'] ?? 'no response', PHP_EOL; foreach ($client->webhooks->iterateDeliveries('whe_3f9c2a7b1e4d8f60a5c7b92d') as $delivery) { echo $delivery['eventType'], ' ', $delivery['status'], ' ', $delivery['responseCode'] ?? '-', ' ', $delivery['error'] ?? '', PHP_EOL;}test एक signed कृत्रिम email.sent event post करता है और प्रयास पूरा होने का इंतज़ार करता है। आपका receiver चाहे जो जवाब दे, यह सामान्य रूप से लौटता है, इसलिए इस पर नहीं कि कॉल ने throw किया या नहीं, बल्कि $result['delivery']['status'] पर branch करें। 4xx एक उपयोगी जवाब है: URL तक पहुँचा जा सकता है और अस्वीकार आपके अपने handler से आया, अक्सर उसकी signature जाँच से।
null responseCode का मतलब है कि कोई जवाब आया ही नहीं (DNS, TLS, टाइमआउट), जो 0 कहने वाले जवाब से अलग तथ्य है। हर पंक्ति में attempt और maxAttempts होते हैं, इसलिए कई पंक्तियाँ एक event बता सकती हैं: उनमें एक जैसा eventId event है, और attempt संख्या प्रयास है। nextAttemptAt बताता है कि किसी पंक्ति के बाद अपने आप होने वाला retry कब होना है।
इसे दोबारा भेजना
$detail = $client->webhooks->getDelivery('whe_3f9c2a7b1e4d8f60a5c7b92d', 'whd_8c1e4a7f2b9d3e6a0c5f1b28');echo json_encode($detail['payload'], JSON_THROW_ON_ERROR), PHP_EOL;echo $detail['responseBody'] ?? 'no answer', ' ', $detail['replayRefusal']['code'] ?? 'replayable', PHP_EOL; $replay = $client->webhooks->replayDelivery('whe_3f9c2a7b1e4d8f60a5c7b92d', 'whd_8c1e4a7f2b9d3e6a0c5f1b28');echo $replay['delivery']['status'], ' ', $replay['delivery']['responseCode'] ?? 'no response', PHP_EOL;जो delivery लगातार विफल होती रहे, उसे 8 बार तक आज़माया जाता है: तुरंत, फिर 1 मिनट, 5 मिनट, 30 मिनट, 2 घंटे, 5 घंटे, 10 घंटे और फिर 10 घंटे बाद, कुल मिलाकर लगभग साढ़े 27 घंटे। केवल वही विफलता दोहराई जाती है जिसे दोहराना सार्थक हो: कोई जवाब नहीं, 408, 425, 429 या कोई 5xx। replay सहेजे गए event को उसी id, type, createdAt और data के साथ फिर भेजता है, इसलिए जो receiver पहले से संभाली गई ids को छोड़ देता है, वह इसे वही event मानता है जिसे वह जानता है। केवल signature नया होता है।
replayDeliveryएक इवेंट अभी भेजता है और लौटाता है कि आपके सर्वर ने क्या जवाब दिया। यह डिलीवर हो चुके प्रयास पर भी काम करता है और इस पर कभी पुनः प्रयास नहीं होता। भेजने से पहले उस इवेंट के अपने-आप होने वाले वे पुनः प्रयास जो शुरू नहीं हुए, रोक दिए जाते हैं: replay डिलीवर होने पर वे रद्द ही रहते हैं, और विफल होने पर अपने शेड्यूल पर फिर शुरू हो जाते हैं।- अगर उसी event का अपने आप होने वाला retry उसी समय भेजा जा रहा हो, तो
replayDeliveryकुछ नहीं भेजता और 409retry_in_progressthrow करता है, और जब उसका कोई दूसरा replay अभी भेजा जा रहा हो तो यह 409replay_in_progressthrow करता है, इसलिए आपके receiver को एक साथ दो कॉपियाँ कभी नहीं मिलतीं, एक ही पल में भेजे गए दो replays से भी नहीं। कुछ सेकंड रुकें औरgetDeliveryपढ़ें, क्योंकि वह retry या replay उसे पहुँचा सकता है। replay एक बार में एक event है: कोई कॉल हर विफल delivery को फिर से नहीं भेजती। - यह बंद किए गए endpoint (
webhook_disabled), ऐसे event के लिए जिसे endpoint अब नहीं सुनता (event_not_subscribed) या अब कवर नहीं करता (event_out_of_scope), और बिना सहेजे गए event वाले प्रयास (delivery_not_replayable) के लिए भी 409 throw करता है। हर एकConflictExceptionहै, औरOpenEmail\Constants\WebhookReplayErrorCodesइन codes के नाम देता है।getDeliveryयह जवाब पहले सेreplayRefusalके रूप में बताता है, जो replay हो सकने पर null होता है और वरनाcodeऔरmessageवाला array।
पैकेज replayDelivery को अपने आप कभी retry नहीं करता, क्योंकि खोए हुए जवाब के बाद retry करने से event फिर से भेजा जाता।
पैरामीटर: webhooks->create
urlstringआवश्यक- deliveries कहाँ POST होती हैं। सिर्फ़ HTTPS, और होस्ट `localhost`, `.localhost`, `.local` या `.internal` नाम, या loopback, private, carrier-grade NAT, link-local, multicast या unique local IP literal नहीं हो सकता। यह आपके दिए पते पर सर्वर-साइड रिक्वेस्ट है, इसलिए ये `url` पर 422 `invalid_webhook_url` हैं। जाँच hostname को लिखे अनुसार पढ़ती है, और हर delivery होस्ट को फिर से देखती है और इन श्रेणियों के किसी पते पर भेजने से इनकार करती है। deliveries कभी redirect का पालन नहीं करतीं, इसलिए अंतिम पता register करें। जो सहेजा जाता है वह आपके भेजे हुए का URL parser द्वारा बनाया गया रूप है, इसलिए `https://acme.com` `https://acme.com/` के रूप में वापस पढ़ा जाता है।
eventTypesarray- कौन-से events इस endpoint तक पहुँचते हैं: `OpenEmail\Constants\WebhookEvents` का कोई भी मान। `create` array को मौजूद events की संख्या तक सीमित करता है, इसलिए उससे एक ज़्यादा होने पर `eventTypes` पर 422 है, और `update` इसे सीमित नहीं करता। सिर्फ़ लंबाई सीमित है, और दोहराया गया नाम ठीक वैसे ही सहेजा और वापस पढ़ा जाता है जैसे आपने भेजा। छोड़ने या ख़ाली रखने पर यह ख़ाली सूची के रूप में सहेजा जाता है, इसीलिए यह `['*']` के रूप में वापस पढ़ा जाता है, और इसका मतलब है `email.replied` को छोड़कर हर `email.*` event, आज चौदह, और कभी भी डोमेन, suppression, file या form परिवार नहीं। बाद में जोड़ा गया परिवार कभी ऐसे endpoint तक नहीं पहुँचता जिसने उसका नाम न लिया हो, इसलिए कोई integration किसी रिलीज़ की वजह से ऐसा आकार पाना शुरू नहीं कर सकता जो उसने कभी देखा न हो।
descriptionstring- endpoint का एक लेबल, अधिकतम 200 अक्षर, ताकि वेबहुक की सूची URLs के column के बजाय नामों की तरह पढ़ी जाए। छोड़ने पर यह null के रूप में सहेजा और लौटाया जाता है। null पास करने के बजाय कुंजी छोड़ दें: क्लाइंट null को वैसे ही भेजता है, और `create` उसे 422 के साथ अस्वीकार करता है।
addressAllowlistarray- अलग-अलग पते जिनके बारे में यह endpoint सुनता है। कोई इवेंट तब डिलीवर होता है जब उससे जुड़ा पता इस सूची में हो, या उसका डोमेन `domainAllowlist` में हो। दोनों ख़ाली छोड़ें तो endpoint वर्कस्पेस के हर पते के बारे में सुनता है। अधिकतम 50, और जो पता इस वर्कस्पेस का नहीं है वह 422 `invalid_parameter` है।
domainAllowlistarray- पूरे डोमेन जिनके बारे में यह endpoint सुनता है, उनमें बाद में जोड़े गए पतों समेत। डोमेन अपने `domain.*` इवेंट भी लाता है। अधिकतम 25।
apiKeystring- array के अंदर की कुंजी नहीं, बल्कि उसके साथ एक named आर्ग्युमेंट: endpoint को क्लाइंट की कुंजी के बजाय इस API कुंजी से बनाता है।
जवाब: बनाया गया endpoint
camelCase कुंजियों वाला एक array। get, list और update secret के बिना यही आकार लौटाते हैं।
objectstring- हमेशा `webhook`, वही discriminator जो सादा read लौटाता है, क्योंकि secret सामान्य आकार पर एक अतिरिक्त कुंजी है, कोई अलग object टाइप नहीं। `secret` मौजूद है या नहीं, यह इस फ़ील्ड से नहीं, इससे तय होता है कि आपने कौन-सा मेथड कॉल किया।
idstring- endpoint का पहचानकर्ता: `whe_` के बाद 24 hex वर्ण। वेबहुक की हर दूसरी कॉल इसे लेती है: `get`, `update`, `delete`, `rotateSecret`, `test`, `listDeliveries`, `listAllDeliveries`, `iterateDeliveries`, `getDelivery` और `replayDelivery`।
urlstring- सहेजा गया endpoint, जो HTTPS और blocked-host जाँचें पास कर चुका है। यह पार्स किया गया URL है जिसे फिर से serialise किया गया, इसलिए आपकी भेजी स्ट्रिंग के बजाय इस मान से तुलना करें।
descriptionstring or null- आपका दिया हुआ लेबल, या कोई न देने पर null। `'description' => null` भेजने वाला `update` इसे हटा देता है।
eventTypesarray- सदस्यता लिए गए events, या `['*']` जब endpoint ने किसी का नाम नहीं लिया। `['*']` वह तरीका है जिससे खाली संग्रहीत सूची read पर दिखाई जाती है और उसे वापस भेजा नहीं जा सकता, और वह पूरे कैटलॉग के बजाय चौदह संदेश events का प्रतीक है। `create` और `update` केवल शाब्दिक event नाम स्वीकार करते हैं।
enabledbool- क्या डिलीवरी का प्रयास होता है। निष्क्रिय endpoint इवेंट भेजे जाते समय छोड़ दिया जाता है और अपना secret तथा डिलीवरी इतिहास बनाए रखता है। यहाँ हमेशा true, क्योंकि सिर्फ़ `update` `enabled` लेता है।
disabledAtstring or null- लगातार 100 विफल deliveries के बाद सर्वर ने endpoint को कब बंद किया। चालू रहने पर null, और जब आपने उसे ख़ुद बंद किया हो तब भी।
disabledReasonstring or null- सर्वर ने इसे क्यों बंद किया। जब भी `disabledAt` null हो तो null।
consecutiveFailuresint- लगातार विफल deliveries। कोई भी deliver हुआ event इसे 0 पर रीसेट करता है, और `enabled` true पर सेट करने वाला `update` भी।
addressAllowlistarray- अलग-अलग पते जिनके बारे में यह endpoint सुनता है।
domainAllowlistarray- पूरे डोमेन जिनके बारे में यह endpoint सुनता है। दोनों सूचियाँ ख़ाली होने का मतलब वर्कस्पेस का हर पता।
lastDeliveryAtstring or null- आख़िरी delivery “प्रयास” का ISO 8601 timestamp, आख़िरी सफलता का नहीं। विफल POST के बाद भी यह लगाया जाता है, इसलिए यह बताता है कि endpoint को आज़माया गया और `listDeliveries` बताता है कि नतीजा क्या रहा। पहले प्रयास तक null, और इसलिए `create` पर हमेशा null।
createdAtstring- endpoint कब पंजीकृत हुआ, इसका ISO 8601 timestamp। `list` इसी फ़ील्ड के अनुसार सबसे नए endpoint पहले लौटाता है।
secretstring- HMAC-SHA-256 कुंजी जो हर डिलीवरी के `X-OpenEmail-Signature` पर हस्ताक्षर करती है: `whsec_` के बाद 43 base64url वर्ण, और वही जो आप prefix समेत `OpenEmail::verifyWebhookSignature` को पास करते हैं। इसे `create` और `rotateSecret` लौटाते हैं, और कोई नहीं। कोई read इसे कभी नहीं लौटाता, इसलिए इसे अभी सहेज लें। खोया हुआ secret सिर्फ़ `rotateSecret` से बदला जा सकता है, जो पुराने को तुरंत अमान्य कर देता है।
लॉग फ़िल्टर करना
$failed = $client->webhooks->listWorkspaceDeliveries(status: 'failed', since: new \DateTimeImmutable('-1 day')); foreach ($failed as $delivery) { echo $delivery['endpointId'], ' ', $delivery['eventType'], ' ', $delivery['responseCode'] ?? '-', PHP_EOL;} $history = $client->webhooks->listActivity('whe_3f9c2a7b1e4d8f60a5c7b92d'); foreach ($history as $change) { echo $change['type'], ' ', $change['actor']['label'] ?? 'OpenEmail', PHP_EOL;}listDeliveries एक endpoint पढ़ता है और listWorkspaceDeliveries हर endpoint, या वे जिनके नाम endpointIds: देता है, array या कॉमा से अलग की गई एक स्ट्रिंग के रूप में, और दोनों status: (delivered या failed), since: और until: लेते हैं, जो console के Deliveries टैब के फ़िल्टर हैं। listActivity और listWorkspaceActivity audit log पढ़ते हैं: किसने क्या बनाया, बदला, चालू-बंद किया, rotate किया, test किया, replay किया या हटाया। हर एक के साथ एक listAll और एक iterate संस्करण है, जैसे listAllDeliveries और iterateDeliveries, और वर्कस्पेस log की हर पंक्ति में endpointId होता है। webhooks->stats आपकी चुनी अवधि के लिए Analytics टैब के पीछे की संख्याएँ लौटाता है।
since: और until: एक DateTimeInterface या ISO 8601 स्ट्रिंग लेते हैं, और सिर्फ़ तारीख़ वाली स्ट्रिंग का मतलब उस दिन की UTC आधी रात है। until: का since: से बाद का होना ज़रूरी है, वरना कॉल errorCode में invalid_parameter वाला InvalidRequestException throw करती है।