NAV
Go Shell Ruby Python Javascript

Introduction

Welcome to the Hanami API! You can use our API to access Hanami API endpoints, which can get information on your domains, alias and even fetch your email with a REST interface.

We have language bindings in Shell, Ruby, and Python! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.

This is document for Hanami API, If you want general documents/guides on setting up hanami email forwarding, check out documents, or contact us at support@hanami.run

API Endpoint

Root API URL: https://api.hanami.run. The API is versioning. Currently we only have v1 so the base API url is https://api.hanami.run/v1

Resources URls are computed from this root api url. Before making an API Request, you would need to get an API key in api dashboard.

All API needs to set a Content-Type: application/json header.

Authentication

To authorize, use this code:

package main

import (
	"fmt"
	"net/http"
	"io/ioutil"
)

func main() {
	url := "https://api.hanami.run/v1/mails?limit=20"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Add("apikey", "api-key")

	res, _ := http.DefaultClient.Do(req)
}
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://api.hanami.run/v1/mails?limit=20")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

request = Net::HTTP::Get.new(url)
request["apikey"] = 'apikey'

response = http.request(request)
import http.client

conn = http.client.HTTPSConnection("api.hanami.run")

payload = ""

headers = {
    'apikey': "api-key"
    }
conn.request("GET", "/v1/mails?limit=20", payload, headers)
# With shell, you can just pass the correct header with each request
curl "api_endpoint_here"
  -H "apikey: api-key"
// Basically set the header on any of HTTP API Client
// Example with built-in http request
const http = require("https");

const options = {
  "headers": {
    "apikey": "api-key-here",
  }
};

const req = http.request(options, function (res) {
});

Make sure to replace meowmeowmeow with your API key.

Hanami requires an API key to pass on header to allow access to the API. Users who are on professional or business plan can get an API key in our dashboard api.

Hanami expects for the API key to be included in all API requests to the server in a header that looks like the following:

apikey: sk_123_apikey_here

MailLog

MailLog API allows you to get all emails to your domains or a specificed domain.

To use this features, you need to enable maillog on your domains, otherwise empty responses are returned. Depend on your log levels, you will have more or less data. If you enable full log, you will have access to full email contents. If you didn’t choose to log subject and body, the subject and body will be redacted.

Get All Emails

package main

import (
	"fmt"
	"net/http"
	"io/ioutil"
)

func main() {

	url := "https://api.hanami.run/v1/mails?limit=20"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("apikey", "api-key")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://api.hanami.run/v1/mails?limit=20")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

request = Net::HTTP::Get.new(url)
request["apikey"] = 'api-key'

response = http.request(request)
puts response.read_body
import http.client

conn = http.client.HTTPSConnection("api.hanami.run")

payload = ""

headers = {
    'apikey': "api-key"
    }

conn.request("GET", "/v1/mails?limit=20", payload, headers)

res = conn.getresponse()
data = res.read()

print(data.decode("utf-8"))
curl --request GET \
  --url 'https://api.hanami.run/v1/mails?limit=20' \
  --header 'apikey: api-key'
const fetch = require('node-fetch');

let url = 'https://api.hanami.run/v1/mails';

let options = {
  method: 'GET',
  qs: {limit: '20'},
  headers: {
    apikey: 'api-key',
  }
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error('error:' + err));

The above command returns JSON structured like this:

[
{
  "data": [
    {
      "id": 50064,
      "from": "from@foo.com",
      "to": [
        "vinh@hanami.run"
      ],
      "subject": "Server status",
      "created_at": "2021-04-15T17:11:29.864Z",
      "status": "sent",
      "body": "This is the body",
      "htmlbody": "If the email has html content"
		},
    {
      "id": 50063,
      "from": "from2@foo.com",
      "to": [
        "vinh@hanami.run"
      ],
      "subject": "Server status 2",
      "created_at": "2021-04-15T17:11:29.864Z",
      "status": "sent",
      "body": "This is the body 2",
      "htmlbody": ""
		}
  }
]

This endpoint retrieves all emails under your accounts or belongs to a single domain.

HTTP Request

GET http://api.hanami.run/v1/mails

Query Parameters

Parameter Default Description
domain empty If set to non empty string, will only include emails belong to that domain.
status send can be sent, spam or outgoing. Default is sent to only include email that pass spam filter.
limit 20 a number between 1 and 100 to limit how many emails are returned.

Get a Specific Email

package main

import "github.com/bep/kittn/auth"

func main() {
	api := auth.Authorize("meowmeowmeow")

	_ = api.GetKitten(2)
}
require 'kittn'

api = Kittn::APIClient.authorize!('meowmeowmeow')
api.kittens.get(2)
import kittn

api = kittn.authorize('meowmeowmeow')
api.kittens.get(2)
curl "http://example.com/api/kittens/2"
  -H "Authorization: meowmeowmeow"
const kittn = require('kittn');

let api = kittn.authorize('meowmeowmeow');
let max = api.kittens.get(2);

The above command returns JSON structured like this:

{
  "id": 50063,
  "from": "from2@foo.com",
  "to": [
    "vinh@hanami.run"
  ],
  "subject": "Server status 2",
  "created_at": "2021-04-15T17:11:29.864Z",
  "status": "sent",
  "body": "This is the body 2",
  "htmlbody": ""
}

This endpoint retrieves a specific emails.

HTTP Request

GET https://api.hanami.run/v1/mails/<ID>

URL Parameters

Parameter Description
ID The ID of the email to retrieve

Email Aliases

This endpoints allow you to create email alias on your domain programmatically. All request should have Content-Type: application/json header. Before using this endpoint, you have to add the domain into our dashboard and complete the setup.

An use case is to dynamically setup alias for your user.

Create an alias

curl --request POST \
  --url 'https://api.hanami.run/v1/domains/your-domain-here/aliases' \
  --header 'Content-Type: application/json' \
  --header 'apikey: your-api-key-here' \
  --data '{
	  "from": "alias",
	  "to": "destional-email-address"
   }'

The above command returns JSON structured like this:

{
  "id": 34,
  "from": "from",
  "to": "my-personal-email@example.com",
  "status": "activated"
}

Before use this, you will need setup your domain in our dashboard first. Once your domain is all setup, you can started to create alias using this API.

HTTP Request

POST http://api.hanami.run/v1/domains/your-domain-here/aliases

Request payload

A Json body include below fields

{ “from”: “alias on your domain”, “to”: “where to send the email to” }

Let’s take an example. Let’s say my domain is sen.run and I want to forward vinh@sen.run to my personal email at vinh@hanami.run, I need to make a request like this:

POST http://api.hanami.run/v1/domains/sen.run/aliases { “from”: “vinh”, “to”: “vinh@hanami.run” }

Errors

The Hanami API uses the following error codes:

Error Code Meaning
400 Bad Request – Your request is malform, check document to send the right parameters
401 Unauthorized – Your API key is wrong
404 Not Found/No Permission – The specified resources could not be found or the API’s account has no access to the resources.
405 Method Not Allowed – You tried to access a kitten with an invalid method
422 Invalid/Malform request data – Double check our doc or contact support@hanami.run
429 Too Many Requests – You’re requesting too many resources! Slow down!
500 Internal Server Error – We had a problem with our server. Try again later.
503 Service Unavailable – We’re temporarially offline for maintanance. Please try again later.