bark-apns 0.1.0

Direct APNs client for sending Bark notifications.
Documentation

bark-apns

Direct APNs client for sending Bark notifications.

This crate talks to APNs directly with an iOS device token, bypassing the Bark server entirely. Messages can also be sent with Bark-compatible encryption, so notification content stays private while delivery remains fast and direct.

Key Features

  • ✨ First-class serde payloads: Uses strongly typed payload models and serde serialization throughout, avoiding brittle hand-built JSON.
  • 🛡️ Correct Bark encryption semantics: Validates algorithm, mode, key, and IV up front, supports all Bark AES options, and serializes encrypted pushes exactly as Bark expects.
  • 🚀 Lean, direct APNs delivery: Sends straight to APNs with no third-party relay or self-hosted backend in the path, keeping delivery fast, simple, and private.

Usage

Send a simple message

use bark_apns::{Bark, Message};

fn main() -> bark_apns::Result<()> {
    let bark = Bark::new()?;
    let message = Message::new()
        .title("Deploy")
        .body("done")
        .group("ops");

    bark.send(&message, ["device-token-from-bark-app"])?;
    Ok(())
}

Send a markdown message

use bark_apns::{Bark, Message};

fn main() -> bark_apns::Result<()> {
    let bark = Bark::new()?;
    let message = Message::new()
        .title("Deploy")
        .markdown("## Deploy\n\n- status: **done**\n- target: `production`");

    bark.send(&message, ["device-token-from-bark-app"])?;
    Ok(())
}

[!NOTE] Bark parses Markdown with Apple's Swift Markdown package and its own renderer. It supports paragraphs, headings, block quotes, bold, italic, strikethrough, inline code, code blocks, links, images, ordered and unordered lists, nested lists, task-list checkboxes, soft breaks, and hard line breaks. In notification banners, Bark uses the rendered plain-text body and collapses repeated blank lines, so styling such as bold, italic, link color, and code font is not preserved there.

Send an encrypted message

use bark_apns::{Bark, Encryption, EncryptionAlgorithm, EncryptionMode, Message};

fn main() -> bark_apns::Result<()> {
    let bark = Bark::new()?;
    let encryption = Encryption::new(
        EncryptionAlgorithm::AES128,
        EncryptionMode::CBC,
        "1234567890123456",
    )?;

    let message = Message::new()
        .title("Deploy")
        .body("done")
        .markdown("**Deploy** finished")
        .group("ops")
        .encryption(encryption);

    bark.send(&message, ["device-token-from-bark-app"])?;
    Ok(())
}

The payload is built with serde, not string concatenation. Encrypted pushes place Bark request fields in the encrypted ciphertext JSON and leave only ciphertext and iv in APNs custom user info.

Error Handling

Library APIs return bark_apns::Result<T>, a typed Result<T, bark_apns::Error>. Applications can still use anyhow::Result at their own boundary:

fn run() -> anyhow::Result<()> {
    bark_apns::Bark::new()?;
    Ok(())
}

License

This project is licensed under the MIT license.