1. Home
  2. API docs
  3. Go

Email verification API in Go

To verify an email in Go, parse it with net/mail, then send a GET request to https://simpleverifier.com/api/v1/verify with an Authorization: Bearer header using an http.Client that has a 30-second timeout. Decode the JSON status: valid, risky or invalid. On an error, log it and let the address through.

By SimpleVerifier Team

Before you start

  • Create a key on the API keys page. Keys start with sv_live_ and are shown once.
  • Set SIMPLEVERIFIER_KEY in the environment the binary runs in.
  • API access is included in the Pro plan ($29.99/month) and the Email + Phone plan ($49.99/month). See pricing.

1. Add the package

Standard library only. The request uses the caller's context, so a cancelled HTTP request cancels the check too.

simpleverifier/simpleverifier.go
// Package simpleverifier checks email addresses with the SimpleVerifier API.
package simpleverifier

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/mail"
	"net/url"
	"os"
	"time"
)

const apiURL = "https://simpleverifier.com/api/v1/verify"

var client = &http.Client{Timeout: 30 * time.Second}

// Result is the JSON body the verify endpoint returns.
type Result struct {
	Email          string `json:"email"`
	Status         string `json:"status"` // "valid", "risky" or "invalid"
	Reason         string `json:"reason"`
	MailboxChecked bool   `json:"mailbox_checked"`
}

// EmailStatus returns "valid", "risky" or "invalid". When the API could not
// answer it returns "" and an error; callers should let the address through.
func EmailStatus(ctx context.Context, email string) (string, error) {
	addr, err := mail.ParseAddress(email)
	if err != nil || addr.Address != email {
		return "invalid", nil // fails the local syntax check, no API call made
	}

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL+"?email="+url.QueryEscape(email), nil)
	if err != nil {
		return "", err
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("SIMPLEVERIFIER_KEY"))

	res, err := client.Do(req)
	if err != nil {
		return "", err // timeout or network error
	}
	defer res.Body.Close()

	if res.StatusCode != http.StatusOK {
		return "", fmt.Errorf("simpleverifier: HTTP %d", res.StatusCode) // 401, 402, 429, 503
	}

	var result Result
	if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
		return "", err
	}
	return result.Status, nil
}

2. Use it in a handler

The method pattern in HandleFunc needs Go 1.22 or later.

main.go
package main

import (
	"log"
	"net/http"
	"strings"

	"example.com/app/simpleverifier"
)

func signupHandler(w http.ResponseWriter, r *http.Request) {
	email := strings.TrimSpace(r.FormValue("email"))

	status, err := simpleverifier.EmailStatus(r.Context(), email)
	if err != nil {
		log.Printf("simpleverifier unavailable, accepting without a mailbox check: %v", err)
	}
	if status == "invalid" {
		http.Error(w, "This email address cannot receive mail. Please check it.", http.StatusUnprocessableEntity)
		return
	}

	// Save the signup here. status is "valid", "risky" or "" (API unavailable).
	w.WriteHeader(http.StatusCreated)
}

func main() {
	http.HandleFunc("POST /signup", signupHandler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

What the API returns

GET or POST https://simpleverifier.com/api/v1/verify with email runs the syntax, domain, disposable-domain and live mailbox checks in one call and returns:

{
  "email": "jane@company.com",
  "status": "valid",
  "reason": "Mailbox exists",
  "mailbox_checked": true
}

Every snippet above follows the same rule: only a successful response with status set to invalid blocks a person.

ResultWhat it meansWhat to do
validThe mail server confirmed the mailbox exists.Accept.
riskyThe domain is real but the mailbox couldn't be confirmed: catch-all domains, role addresses like info@, providers that hide mailbox status.Accept on signup forms. Store the status and keep these out of cold campaigns.
invalidBad format, no mail server, a disposable domain, or the mailbox doesn't exist.Reject and ask the person to check the address.
timeout, 429 or 503The check didn't finish: a slow mail server, too many calls this minute, or a brief outage.Accept (fail open) and log it. Re-check later if it matters.
401 or 402The key is wrong or revoked, or the subscription isn't active.Accept, and alert yourself: every check is being skipped until it's fixed.

Errors return JSON with an error message. Each key can make 120 calls a minute; for thousands of addresses, upload a CSV in the dashboard instead.

Phone numbers and spreadsheets

The same key works with /api/v1/phone?phone=…&country=… to validate a phone number and normalise it to E.164, with live carrier lookups on the Email + Phone plan. The request and response are in the API reference. To check a column of addresses without code, use the Google Sheets add-on with the same key.

Common questions

Why check addr.Address != email after net/mail.ParseAddress?
ParseAddress also accepts display-name forms such as Jane <jane@company.com>. Comparing the parsed address to the input rejects those, so only a bare address reaches the API.
Can I verify several addresses concurrently?
Yes, but keep the total under 120 calls a minute per key, for example with a time.Ticker or golang.org/x/time/rate. For large lists, upload a CSV in the dashboard instead.
How much does the SimpleVerifier API cost?
API access is included in the paid plans: Pro at $29.99/month and Email + Phone at $49.99/month. There are no per-call credits. Each key can make 120 calls a minute.
Should I reject risky addresses?
Not on a signup or contact form. Risky means the mailbox couldn't be confirmed, which includes every address at a catch-all company domain. Accept it, store the status, and leave risky addresses out of cold outreach.
What if the API is slow or down?
Let the address through. A mailbox check can take several seconds when a mail server is slow, so cap the wait at about 30 seconds (less on a busy form) and treat a timeout, a 429 or a 503 as unknown rather than invalid.

Ready to clean your email and phone lists?

Start verifying emails and phone numbers today and boost your deliverability.

Get Started

Cancel anytime • No setup required