AnnouncementsIntroducing Arkoren

    Menu

    Overview

    Submit typed push messages, choose retention, and distinguish acceptance from browser display.

    What's on this page
    1. Build immutable messages from typed application input and authorized recipients.
    2. Choose offline retention and handle uncertain acceptance without automatic retries.
    3. Observe submission outcomes without treating them as delivery or display confirmation.
    On this page

    Push notifications tell a customer about an update even when your site is not open. A push.Sender submits one message to its configured driver; the browser’s service worker displays it. Provider acceptance does not establish delivery or display, and push is not a durable notification inbox.

    A subscription contains a browser-issued endpoint and encryption keys. Your application stores it for the signed-in user, authorizes recipient selection, and handles replacement or removal. Arkoren does not register devices, store subscriptions, route between providers, or retry sends. Configure a sender in Drivers and obtain subscriptions through Browser Integration.

    Preparing Messages

    These focused examples assume a configured sender, a context.Context named ctx, and a push.Subscription named subscription loaded from an authorized registration record. Import arkoren.dev/core/service/push. Snippets retain error assignments but omit routine propagation; complete functions and security decisions handle errors before proceeding.

    For an order update, keep application input typed before translating it into the message’s string metadata:

    type OrderNotice struct {
    	OrderID string
    	Path    string
    }
    
    notice := OrderNotice{OrderID: "123", Path: "/orders/123"}

    Choose the subscription on the server, not from an arbitrary recipient in the request. Required arguments identify that recipient and a nonempty UTF-8 title; the construction callback adds optional body text and application data:

    message := push.NewMessage(subscription, "Order shipped", func(notification *push.MessageBuilder) {
    	notification.Body("Your order is on its way.")
    	notification.Data(map[string]string{
    		"order_id": notice.OrderID,
    		"url":      notice.Path,
    	})
    })

    Data accepts string values, not arbitrary JSON or a provider notification object. Body text and metadata keys and values must also be valid UTF-8. Message is an immutable snapshot: construction copies the map, and Data() returns a detached copy. Data replaces earlier metadata rather than merging it. Err() and Validate() expose the first declaration error, even if a later callback supplies a valid replacement.

    Pass a push.Subscription or push.Token value, not a pointer. Tokens are interpreted only by a driver that supports them; the Web Push driver accepts subscriptions only. Subscription validation checks HTTPS structure and browser encryption keys without network I/O. It does not approve a destination for outgoing requests; driver endpoint policy does that.

    Submitting Notifications

    Submit the published message once through the sender:

    receipt, err := sender.Send(ctx, message)

    Send validates before calling the driver. Invalid portable input never reaches it. A nil error means acceptance; Receipt.ID is optional opaque acceptance metadata and can be empty. Web Push deliberately returns an empty ID rather than exposing a sensitive provider URL.

    Do not put sensitive information in display text: notifications can appear on a locked device. Keep subscription endpoints, keys, native tokens, payloads, and receipt IDs out of general logs and telemetry. Top-level diagnostics redact recipient details, but explicitly unwrapped native errors can still contain URLs.

    Choosing Retention

    The time to live (TTL) requests how long the provider can retain an update while the browser is offline. It is neither a delivery deadline nor a promise that the provider stores or displays the notification.

    The sender requests 24 hours by default. For a status update that becomes stale after five minutes, import time and override retention for this send:

    receipt, err := sender.Send(ctx, message, push.TTL(5*time.Minute))

    An omitted option or push.TTL(0) inherits the sender default; a negative option requests no offline storage. No-store does not prevent immediate delivery. Drivers shows how to change the sender default. Direct driver calls differ: raw push.SendConfig{TTL: 0} means no-store, and a negative raw TTL is invalid. Web Push rounds positive durations down to whole seconds, so a duration below one second also becomes no-store.

    Handling Outcomes

    Classify failures with standard-library errors.Is. Check push.ErrOutcomeUnknown before cancellation or provider failures: a wrapped or joined error can match several causes without resolving whether acceptance occurred. Every failed send returns a zero receipt.

    Error Application Response
    push.ErrOutcomeUnknown Acceptance is uncertain; decide whether a duplicate is acceptable before replaying.
    push.ErrInvalidMessage Correct input, endpoint policy, payload size, or retention before resubmission.
    push.ErrUnsupported Choose a recipient or operation supported by the configured driver.
    push.ErrNotFound Invalidate only the stored registration version used for this send.
    push.ErrRateLimited Apply an explicit bounded scheduling policy.
    push.ErrUnavailable Report availability failure and apply application policy; do not delete the registration.

    Web Push maps authoritative HTTP 404/410 responses to ErrNotFound. Authentication failures do not prove expiry: repair credentials rather than deleting live subscriptions. Conditional invalidation prevents an older send from deleting a registration refreshed while the request was in flight.

    A timeout after dispatch can leave acceptance unknown. Automatic replay can produce duplicate notifications. Neither the sender nor the Web Push driver retries automatically or provides exactly-once delivery.

    Permission revocation, offline expiry, operating-system settings, and worker failures can prevent display after acceptance. Use Testing to check application submission and browser display as separate outcomes.

    Observing Submissions

    For optional in-process observations, configure push.Builder.Events with a shared event bus as shown in sender settings. push.Accepted and push.Failed report returned driver outcomes, not delivery. Their SubmissionEvent contains only duration and a bounded error class.

    Portable preflight failures emit no event. A failed event with ErrorClass == "outcome_unknown" means acceptance could have occurred. Acceptance has an empty class; other classes identify cancellation, deadline, push sentinels, or an unclassified error. Listener failures and panics do not change Send’s result; driver panics propagate without an outcome event. These best-effort observations are not a durable audit log or retry mechanism.

    Telemetry follows the process default on each call unless explicitly selected. It records bounded operation/error classes, never message, recipient, receipt, or native error text. Unknown acceptance takes classification precedence over joined cancellation or deadline errors without replacing their returned causes. See the push instruments for span and metric names.

    For message, recipient, and sender operations, see the push API reference.

    Open a bulk documentation archive?

    This file contains every guide in its scope, not API declarations. Loading it all into an agent can exhaust its context window and increase processing time and cost. For coding tasks, start with the index and read only the relevant pages.

    Use the full archive for offline indexing, bulk processing, or deliberate large-context use.

    Browse the index instead
    Open archive