tickstem/verify

April 22, 2026 · View on GitHub

Go Reference Go Report Card codecov

Go SDK for Tickstem — email verification for production apps.

Checks syntax, MX records, disposable domains, and role-based prefixes before an address touches your database.

Install

go get github.com/tickstem/verify

Quick start

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/tickstem/verify"
)

func main() {
    client := verify.New(os.Getenv("TICKSTEM_API_KEY"))

    result, err := client.Verify(context.Background(), "user@example.com")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(result.Valid)      // true if safe to store
    fmt.Println(result.Disposable) // true if throwaway address
    fmt.Println(result.RoleBased)  // true if generic inbox (admin@, info@, ...)
    fmt.Println(result.Reason)     // explanation when Valid is false
}

Get your API key at app.tickstem.dev.

Usage

Create a client

// Minimal — uses https://api.tickstem.dev/v1
client := verify.New(os.Getenv("TICKSTEM_API_KEY"))

// With options
client := verify.New(apiKey,
    verify.WithBaseURL("http://localhost:8080/v1"),
)

Verify an email

result, err := client.Verify(ctx, "user@example.com")
if err != nil {
    if verify.IsQuotaExceeded(err) {
        // monthly quota hit — upgrade at app.tickstem.dev/dashboard/billing
    }
    log.Fatal(err)
}

if !result.Valid {
    return fmt.Errorf("email not accepted: %s", result.Reason)
}

if result.RoleBased {
    // warn but don't block — some teams share an inbox
}

What gets checked

CheckWhat it catchesWhy it matters
SyntaxMalformed addresses (user@@example, missing TLD)Reject obviously bad input before any network call
MX lookupDomains with no mail server (gmial.com, abandoned domains)Catch typos and dead domains that pass syntax checks
DisposableThrowaway services (Mailinator, Guerrilla Mail, 200+ others)Block single-use signups that inflate user counts and churn immediately
Role-basedGeneric inboxes (admin@, info@, noreply@, support@, ...)Flag addresses shared by teams or bots — poor engagement, not tied to a real person

No SMTP probing — the recipient mail server is never contacted.

Retrieve history

page, err := client.ListHistory(ctx, verify.ListHistoryParams{
    Limit:  50,
    Offset: 0,
})
for _, v := range page.Verifications {
    fmt.Printf("%s  valid=%v  disposable=%v\n", v.Email, v.Valid, v.Disposable)
}

Error handling

result, err := client.Verify(ctx, email)
if err != nil {
    if verify.IsUnauthorized(err) {
        // invalid or revoked API key
    }
    if verify.IsQuotaExceeded(err) {
        // monthly verification limit reached
    }
    var apiErr *verify.APIError
    if errors.As(err, &apiErr) {
        fmt.Println(apiErr.StatusCode, apiErr.Message)
    }
}

Pricing

PlanVerifications/monthPrice
Free500$0
Starter5,000$12/mo
Pro50,000$29/mo
Business500,000$79/mo

View full pricing →

License

MIT