This website uses cookies to enhance the user experience.

Developers API

TEMPORABLE API

Temporable was born because we needed a disposable email service with a great, easy to use API. At that time we were working on a project on which we needed service like that and none of the available options did fit us so we ended up creating our own solution, and years later, offered it to the public.

At this point we offer two API integrations, one for the Mail API and another for the Proxy API, you can use the API you have purchased the subscription for.

When we designed the API one of the main goals we had was that it should be easy and painless to integrate and use, the idea was that anybody with basic programming skills could use the API to reach their goals, we do not have overly complicated authentication methods, just the old and good API keys.

All the interaction between the API is done via HTTP requests to our API endpoint and we use the HTTP verbs POST GET DELETE and JSON to perform actions on the different services we offer.

OBTAINING THE API TOKEN

In order to start calling our API you need a API token/key, which is provided when you buy any of our plans.

The amount of API tokens you can create is limited by your purchased subscription, refer to the Security section in the console to see your current token limit.

All the API tokens share a set of limits which are based on the subscription plan you purchased.

Proxy API tokens does not have any request limits.

The same API token can be used for both APIs but each one have their own limits.

In order to create an API token you must visit our console and refer to the Security menu to manage your keys.

API SCHEMA DEFINITION

When calling our API you must follow a set of rules to avoid issues, specially when it comes down to errors and handling of the returned data.

Each section of this document explains the details of each individual service along with the returned data format, however, all of them shares a common structure

// Request object body
{
	messageId: 321
}

// Response object body
{
	"error": null,
	"success": true,
	"data": {
		"id": 32,
		"from": "[email protected]",
		"to": ["[email protected]"],
		"subject": "Verify your account at SomePhishingWebsite!",
		"senderIp": "10.0.23.2",
		"senderHostname": "local.temporal.email.com",
		"headers": [],
		"cc": [],
		"bcc": [],
		"messageId": "",
		"inReplyTo": "",
		"content" : {
			"html": "",
			"text": ""
		},
		"attachments": []	
	}
}

There you can see a example call to the GET /v1/messages endpoint, the request body only includes the needed JSON-encoded parameters to perform the call and the response follows this pattern, see below.

{
	"error": "<error list>",
	"success": "<true if the call suceeded or false otherwise>",
	"data": "<response data for the call>"
}
RESPONSE OBJECT
ParameterTypeDescription
errornull | TemporableAPIErrorThe error parameter contains information about the reason a call has failed. If the call suceeded the value will be null or if it fails it will contain a TemporableAPIError object containing the reason.
successbooleanIf the request succeeded it will be true and false otherwise, to check the reason of the failure check the error field.
dataany | array<any>The format of the data field is dependent upon the service being called, usually contains the response data or null if there's none.
ERROR OBJECT
ParameterTypeDescription
codestringShort error code describing the reason of the request failure, check the error handling section to see the list of errors.
messagestringHuman readable message describing the reason the request has failed.

CALLING THE API

All the API transmission is done over HTTP using standard HTTP messages and verbs to the following API endpoint.

https://api.temporable.com/v1

The usage of HTTPS is mandatory, do not attempt to use HTTP as we don't even run a API service on HTTP.

Messages are authenticated using your API key and the HTTP header Authentication. When using any HTTP client library use your API key as your username and leave the password empty.

In this example 9b54f54a09e23ce0da0107848b1707769053fefc1f005c782b6200a431439e17 is our API key.

GET /v1/message HTTP/1.1
...
Host: api.temporable.com
Authentication: Bearer 9b54f54a09e23ce0da0107848b1707769053fefc1f005c782b6200a431439e17
Content-Type: application/json
...

{
	messageId: 23
}

You can authenticate the API using the apiToken URL parameter but the recommended way is to use the Authentication HTTP header. If you still want to use the apiToken URL parameter, call the API as follows.

https://api.temporable.com/v1/service?apiToken=9b54f54a09e23ce0da0107848b1707769053fefc1f005c782b6200a431439e17

We recommend you to use a HTTP library of your choice to communicate with the API.

ERRORS & HANDLING

Things go wrong sometimes and having a good error handling mechanism is mandatory, when developing your app ALWAYS add error handling code, even if something never fails, it will fail eventually, thank you Murphy.

The Temporable API manages errors via the error field in the API responses, that field is designed to be very versatile and to allow us to implement specific error codes for specific scenarios, we could simply leave the success field alone and call it done however we believe that being verbose with what failed in our side will help the developer find the problem and fix it quickly.

Each API service does have custom error codes and messages however we have defined a common set of errors that are shared between all the services of the API, it's a common practise to create a common error handler in your app to handle all the common errors and then catch the more specific errors on each call.

For example, imagine that we're doing some manteinance on the Temporable API servers and the API returns with the error service_unavailable to all the calls, you could then make a generic error handler that queues the calls for later, when the API might be operative again instead of hammering our servers with calls that leads nowhere.

HTTP ERRORS

All the API calls, either succeeded or failed, returns the HTTP 200/201 status codes, if any other status code is returned (500 for example) treat it as a API downtime scenario.

COMMON ERRORS
error.code fieldDescriptionRecommended Action
service_unavailableThe service is currently not available.Wait some time before making another call
service_overquotaThe Account attached to the key ran out of alloted resources.Renew your subscription to get more resources.
service_ratelimitThe API key is being rate limited.Try to slow down the request rate to avoid hitting the request limit. The limits are subscription-based
service_internalerrorAn internal, unexpected error has ocurred.A temporal failure has ocurred in the system, retry the request again.
key_invalidThe API key is invalid or does not existsVerify that you're using a valid API key and that you copied all the characters.
key_expiredThe API key has expired.The Account attached to the key doesn't have any active subscription
entity_invalidThe specified entity does not exists or is invalid
entity_expiredThe specified entity has expired and it's no longer accesible
parameter_invalidAny of the input parameters are invalid.
parameter_missingA required parameter is missing from the request.
access_deniedYou don't have access to this feature

GET THE LIST OF PROXIES

REQUEST
GET /v1/proxy/list?<filters>

Below is the list of filters for the Proxy service, filters are appended to the URL in the form of URL parameters

You can specify multiple filtering values by repeating the filter in the URL

See the examples below.

// Get the list of proxies matching Argentina as country
GET /v1/proxy/list?country=AR

// Get the list of proxies matching Argentina and Chile as country
GET /v1/proxy/list?country=AR&country=CL

// Get the list of US proxies that supports SOCKS4
GET /v1/proxy/list?country=US&protocol=socks4

// Get the list of US proxies that supports HTTP and SOCKS5
GET /v1/proxy/list?country=US&protocol=http&protocol=socks5
Filter NameTypeDescription
ipIPv4IP address to match.
portintegerPort number to match.
countrystringCountry or list of countries to match, in ISO 3166-1 alfa-2 format
protocolstringProtocol of the proxy, can be any of http, socks4 or socks5
connectionTimeintegerElapsed time until the TCP connection is established.
firstTimeByteintegerElapsed time until the response is received.
downloadSpeedintegerMinimum proxy download speed, in bytes/second
uptimeintegerMinimum uptime, in percentage 0-100
returnAllbooleanSet to 1 or true to return all the matching proxies, else it will return a random one.
anonymitystringFilter out proxies based on the anonymity level provided, as follows.
  • transparent - Transparent proxies pass your original IP to the target, they can see who you are.
  • anonymous - Anonymous proxies identifies themselves as proxies to targets but does not pass your origin IP to the target.
  • elite - Elite or High Anonymity proxies neither identifies themselves as proxies or pass any of your info to the target.
supportsstringFilter out proxies by features supported, see the list below, in order to check for several features separate them with commas.
  • https - Supports FULL HTTPS connection end-to-end via HTTP tunneling.
  • insecurehttps - Supports HTTPS but via a GET request, this is called insecure HTTPS because the proxy can actually see the data you send or receive.
  • cookies - Proxy doesn't tamper or remove the Cookie header.
  • useragent - Proxy doesn't tamper or remove the User-Agent header.
  • referer - Proxy doesn't tamper or remove the Referer header.
  • tunneling - Proxy supports the HTTP CONNECT method to create HTTP tunnels to port 80
  • tcptunneling - Proxy supports the HTTP CONNECT method to create HTTP tunnels to any TCP port.
  • ws - Proxy supports WebSocket connections.
  • wss - Proxy supports TLS/HTTPS WebSocket connections.
RESPONSE
{
   "data":{
      "level":"ELITE",
      "host":"222.245.132.24",
      "port":7302,
      "type":"socks5",
      "supports":{
         "https":true,
         "cookies":true,
         "referer":true,
         "tunneling":false,
         "userAgent":true,
         "webSocket":true,
         "tunnelingTCP":false,
         "insecureHttps":false,
         "secureWebSocket":true
      },
      "stats":{
         "downloadSpeed":0,
         "firstByteTime":0,
         "connectionTime":380
      },
      "country":"CN"
   },
   "error":null,
   "success":true
}
Parameter NameTypeDescription
[].idintegerUnique message identifier
[].readbooleanWhether the message has been read or not. Retrieving the message using the GET /v1/message service will mark the message as read.
[].fromstringSource message address.
[].toarray<string>List of destination addresses
[].subjectstringMessage subject, parsed from the headers.
[].receivedAtintegerUnix timestamp at which the message was received.
[].expiresAtintegerUnix timestamp at which the message will expire and be deleted.
[].hasAttachmentsbooleanWhether the message contains any attachments.
ERRORS
Error codeDescription
offset_invalidThe specified offset is invalid.

LISTING RECEIVED MESSAGES

REQUEST
GET /v1/message/list/:offset
Parameter NameTypeDescription
:offsetintegerOffset to retrieve the messages from, the API returns max 100 messages, to get the message 101 for example you need to pass 100 as the offset. The API won't return any messages if the offset is larger than the count of available messages
RESPONSE
{
	"error": null,
	"data": [{
		"id": 1337,
		"read": true,
		"from": "[email protected]",
		"to": ["[email protected]"],
		"subject": "Verify your account at SomePhishingWebsite!",
		"receivedAt": 1644153984,
		"expiresAt": 1645154007
		"hasAttachments": false
	}, {
		"id": 1352,
		"from": "[email protected]",
		"to": ["[email protected]"],
		"subject": "Hey there, want some scam stuff?",
		"receivedAt": 1642113421,
		"expiresAt": 1643125216
		"hasAttachments": true
	}]
}
Parameter NameTypeDescription
[].idintegerUnique message identifier
[].readbooleanWhether the message has been read or not. Retrieving the message using the GET /v1/message service will mark the message as read.
[].fromstringSource message address.
[].toarray<string>List of destination addresses
[].subjectstringMessage subject, parsed from the headers.
[].receivedAtintegerUnix timestamp at which the message was received.
[].expiresAtintegerUnix timestamp at which the message will expire and be deleted.
[].hasAttachmentsbooleanWhether the message contains any attachments.
ERRORS
Error codeDescription
offset_invalidThe specified offset is invalid.

LISTING CUSTOM DOMAIN RECEIVED MESSAGES

REQUEST
POST /v1/message/domain

{
	domain: "yourcustomdomain.com",
	offset: 0
}
Parameter NameTypeDescription
domainstringName of the domain to retrieve messages for.
offsetintegerOffset to retrieve the messages from, the API returns max 100 messages, to get the message 101 for example you need to pass 100 as the offset. The API won't return any messages if the offset is larger than the count of available messages
RESPONSE
{
	"error": null,
	"data": [{
		id: 1,
		read: false,
		from: '[email protected]',
		to: [ '[email protected]' ],
		subject: 'Temporal email',
		receivedAt: '2022-02-19T11:35:07.360Z'
	}]
}
Parameter NameTypeDescription
[].idintegerUnique message identifier
[].readbooleanWhether the message has been read or not. Retrieving the message using the GET /v1/message service will mark the message as read.
[].fromstringSource message address.
[].toarray<string>List of destination addresses
[].subjectstringMessage subject, parsed from the headers.
[].receivedAtintegerUnix timestamp at which the message was received.
ERRORS
Error codeDescription
offset_invalidThe specified offset is invalid.
entity_invalidThe specifie domain does not exists.

POLLING FOR UNREAD MESSAGES

REQUEST
GET /v1/message/poll
RESPONSE
{
	"error": null,
	"data": [{
		id: 1,
		from: '[email protected]',
		to: [ '[email protected]' ],
		receivedAt: '2022-02-19T11:35:07.360Z'
	}]
}
Parameter NameTypeDescription
[].idintegerUnique message identifier
[].fromstringSource message address.
[].toarray<string>List of destination addresses
[].receivedAtintegerUnix timestamp at which the message was received.

RETRIEVING MESSAGES

REQUEST
GET /v1/message/:id
Parameter NameTypeDescription
:idintegerID of the message to retrieve.
RESPONSE
{
	"error": null,
	"data": {
		"id": 32,
		"read": false,
		"from": "[email protected]",
		"to": ["[email protected]"],
		"subject": "Verify your account at SomePhishingWebsite!",
		"senderIp": "10.0.23.2",
		"senderHostname": "local.temporal.email.com",
		"receivedAt": 1644153984,
		"expiresAt": 1645154007,
		"matchedDomains": ["quickbrownfox.com"]
		"headers": [],
		"cc": [],
		"bcc": [],
		"messageId": "",
		"inReplyTo": "",
		"content" : {
			"html": "",
			"text": ""
		},
		"attachments": []	
	}
}
Parameter NameTypeDescription
idintegerUnique message identifier
readbooleanWhether the message has been read or not.
fromstringSource message address.
toarray<string>List of destination addresses
subjectstringMessage subject, parsed from the headers.
senderIpstringSender network address, either IPv4 or IPv6
senderHostnamestringReversed resolved hostname of senderIp
receivedAtintegerUnix timestamp at which the message was received.
expiresAtintegerUnix timestamp at which the message will expire and be deleted.
matchedDomainsarray<string>List of domains that matched the to field, including your own custom domains.
headersarray<object>Array of objects for the list of headers.
headers[].namestringLowercase name of the SMTP header
headers[].valuestringValue of the SMTP header
ccarray<string>Array of carbon copy addresses.
bccarray<string>Array of blind carbon copy addresses.
messageIdstringIdentifier of the message per the Message-ID field, do not use this as a unique identifier as it can be easily spoofed.
inReplyTostringValue of the In-Reply-To header field.
contentobjectMessage content body
content.htmlstringHTML body of the message, if present
content.textstringPlain text body of the message, if present
attachmentsarray<object>Array of message attachments
attachments[].idintegerAPI ID for this attachment, use this ID when working with the Attachments service
attachments[].cidintegerContent ID for this attachment
attachments[].sizeintegerSize in bytes for the attachment
attachments[].fileNamestringFile name (if any specified) for this attachment
ERRORS
Error codeDescription
entity_invalidThe message ID doesn't exists

DELETING MESSAGES

REQUEST
DELETE /v1/message/:id
Parameter NameTypeDescription
:idintegerID of the message to delete.
RESPONSE
{
	"error": null,
	"data": {
		"deletedId": 32
	}
}
Parameter NameTypeDescription
deletedIdintegerID of the message deleted.
ERRORS
Error codeDescription
entity_invalidThe message ID doesn't exists or has been already deleted.

LISTING ATTACHMENTS

REQUEST
GET /v1/attachment/list/:messageId
Parameter NameTypeDescription
:messageIdintegerID of the message to list the attachments from.
RESPONSE
{
	"error": null,
	"data": [{
		"id": 2172,
		"cid": "logo",
		"size": 32144,
		"fileName": "logo.png",
		"contentType": "image/png",
		"disposition": "inline",
		"checksum": "a306e9271dcc3326d05a87aebf2b5f28737a71d2566ba8faa3a5bf68a2940031",
		"contentUrl": "https://attachment.temporable.com/fIaHBYXafNWCyZPVRdVxZLoUGSyWhjmMLDgLlbiMexGqUMFioZhOdPDYrAQYTJSyvkdSmDMHxNTAOLJEAbzQezuLWgWqNdLweHPI"
		"headers": [
			{
				"name": "content-type",
				"value": "image/png"
			},
			{
				"name": "content-disposition",
				"value": "inline"
			},
			{
				"name": "content-transfer-encoding",
				"value": "base64"
			},
			{
				"name": "content-id",
				"value": "<logo>"
			}
		]
	}, {
		"id": 2173,
		"cid": "antispamemail",
		"size": 32144,
		"fileName": "email_antispam.png",
		"contentType": "image/png",
		"disposition": "inline",
		"checksum": "1d77bb025d23fdcc65a80b498ce7d959d7f7ddcd63c1d2b76bf72dca656816bb",
		"headers": [
			{
				"name": "content-type",
				"value": "image/png"
			},
			{
				"name": "content-disposition",
				"value": "inline"
			},
			{
				"name": "content-transfer-encoding",
				"value": "base64"
			},
			{
				"name": "content-id",
				"value": "<antispamemail>"
			}
		]
	}]
}

Please refer to the GET /v1/attachment endpoint for the parameter descriptions.

ERRORS
Error codeDescription
entity_invalidThe message ID doesn't exists

RETRIEVING MESSAGE ATTACHMENT

REQUEST
GET /v1/attachment/:id
Parameter NameTypeDescription
:idintegerID of the attachment to get
RESPONSE
{
	"error": null,
	"data": {
		"id": 2172,
		"messageId": 3121,
		"cid": "logo",
		"size": 32144,
		"fileName": "logo.png",
		"contentType": "image/png",
		"disposition": "inline",
		"checksum": "a306e9271dcc3326d05a87aebf2b5f28737a71d2566ba8faa3a5bf68a2940031",
		"contentUrl": "https://attachment.temporable.com/fIaHBYXafNWCyZPVRdVxZLoUGSyWhjmMLDgLlbiMexGqUMFioZhOdPDYrAQYTJSyvkdSmDMHxNTAOLJEAbzQezuLWgWqNdLweHPI"
		"headers": [
			{
				"name": "content-type",
				"value": "image/png"
			},
			{
				"name": "content-disposition",
				"value": "inline"
			},
			{
				"name": "content-transfer-encoding",
				"value": "base64"
			},
			{
				"name": "content-id",
				"value": "<logo>"
			}
		"createdAt": 1501740665
		]
	}
}
Parameter NameTypeDescription
idintegerAPI ID of the attachment
messageIdintegerID of the parent message.
cidstringContent ID of the attachment
sizeintegerSize in bytes of the attachment
fileNamestringFile name of the attachment, if any is specified.
contentTypestringMIME type of the attachment body
dispositionstringAttachment disposition in the message.
checksumstringSHA256 hash of the attachment contents.
contentUrlstringURL of the attachment content, download it via a GET request using a HTTP client.
headersarray<object>Array of attachment headers
headers[].namestringLowercase name of the header
headers[].valuestringRaw value of the header
createdAtintegerUNIX timestamp when the attachment was created.
ERRORS
Error codeDescription
entity_invalidThe attachyment ID doesn't exists or belongs to a message that you don't own.

GENERATING EMAIL ADDRESS

Just a quick note, you dont need to call this API service to generate a valid address, as long as the domain is valid you can send email to said domain and it will be delivered at Temporable

This service is just offered as a quick way to generate email addresses based on some parameters, use it when you need it.

REQUEST
POST /v1/domain/address

{
	domain: null,
	tag: null,
	user: null,
	expires: 7200
}
Parameter NameTypeDescription
domainstringoptionalName of the domain to use when generating the address, leave empty to use a random domain from the available list.
tagstringoptionalName of the tag to filter which domains to use, you can use the special tags public and private to include the public or the private domain list. Only used if domain is null
userstringoptionalAddress name value, specifing a name would lead to an address in the format [email protected] leaving it null will generate a random name
expiresintegeroptionalDuration of the email binding, defaults to 2 hours if not specified, see the /domain/bind service for more information.
RESPONSE

Leaving everything default

{
	"error": null,
	"data": {
		expires: "2022-02-15T20:21:49Z",
		address: "[email protected]"
	}
}
Parameter NameTypeDescription
expiresISO 8601 DateExpiration date in ISO 8601 format for the binding.
addressstringAddress generated and bound
ERRORS
Error codeDescription
domain_invalidThe domain isn't a valid domain name or does not exists.
domain_tag_invalidThe domain tag isn't a valid tag name or does not exists
domain_unavailableNo domains are available at this moment to generate an address.
address_existsThere's already a existing binding for the specified address.

BINDING AN EMAIL ADDRESS

REQUEST
POST /v1/domain/bind

{
	address: "[email protected]",
	expires: 7200
}
Parameter NameTypeDescription
addressstringFull domain address to bind, the domain must exist in our system in order to be used.
expiresintegeroptionalNumber of seconds before the binding expires, leaving the field empty will create a binding that expires in two hours, you can specify any number of seconds up to 24 hours. If you need more time you can simply call this function again with the same address and it will overwrite the current binding with the new expiration.
RESPONSE
{
	"error": null,
	"data": {
		expires: "2022-02-15T20:21:49Z",
		address: "[email protected]"
	}
}
Parameter NameTypeDescription
expiresISO 8601 DateExpiration date in ISO 8601 format.
addressstringAddress bound
overwrittenbooleanWether the binding already existed and it was overwritten
ERRORS
Error codeDescription
domain_invalidThe domain isn't a valid domain name or does not exists.
address_invalidThe address is invalid or is not formatted correctly.

UNBINDING AN EMAIL ADDRESS

REQUEST
POST /v1/domain/unbind

{
	address: null
}
Parameter NameTypeDescription
addressnull | string | array<string>Setting this parameter to null will remove all the bindings of the account, you can also specify a single bound address or an array of bound addresses.
RESPONSE
{
	"error": null,
	"data": ["[email protected]", "[email protected]"]
}

LIST ALL AVAILABLE DOMAINS

REQUEST
GET /v1/domain
RESPONSE
{
	"error": null,
	"data": {
		"public": ["fastmail.com", "temporalemail.com", "phishmenot.com"],
		"private": ["helixmanufacturing.com", "quicklaborchange.com", "acmeindustries.com"],
		"custom": ["temporable.com", "myownwebsite.com"]
	}
}
Parameter NameTypeDescription
public[]array<string>List of public available domains for use, the list of domains can change quickly so be sure to not cache it for too long.
private[]array<string>List of domains available for subscriptors, while those domains don't change as quickly as public ones, be sure to check from time to time if new domains are added or removed.
custom[]array<string>Custom domains that you have added to our API, those domains can only be used by the API/account who created them.

ADDING YOUR OWN DOMAINS

REQUEST
POST /v1/domain

{
	"domain": {
		"name": "yournewcustomdomain.com",
		"tags": ["registration", "verification"]
	}
}
Parameter NameTypeDescription
domainstring | array<string>Either an array of domain objects or a single domain object. We recommend to configure the domain DNS MX records to point to Temporable before adding the domain to avoid messages failing to be delivered due to the MX records not being configured or not yet propagated across the internet.
domain.namestringName of the domain to be added
domain.tagsoptional array<string>List of tags to assign to the domain, the tags can be used at address generation time to specify a domain or groups of domains that shares a single tag. By assigning a tag to several domains you can generate a random address using said tag and randomly get any of the domains matching the tag.
RESPONSE
{
	"error": null,
	"data": "yournewcustomdomain.com"
}
ERRORS
Error codeDescription
domain_invalidThe domain isn't a valid domain name.
domain_existsThe domain name already exists, either in your account or in another account.

DELETING A DOMAIN

REQUEST
DELETE /v1/domain

{
	"domain": "yournewcustomdomain.com"
}
Parameter NameTypeDescription
domainstringName of the domain to delete. At this point you can only delete your own custom domains, in future API version we will add the ability to disable public/private domains per request.
RESPONSE
{
	"error": null,
	"data": null
}
ERRORS
Error codeDescription
domain_invalidThe domain isn't a valid domain name or does not exists.

WORKING WITH WEBHOOKS

WebHooks are the best way to get notified of incoming events in the API related with your domains

CREATING WEBHOOK FILTERS

RETRIEVING WEBHOOK DATA