Import suppressed addresses
/api/v1/email-suppressions/importBlock up to 10,000 addresses in one request, for example the unsubscribes you are bringing over from another email service. Mailyte will not send to them again until you remove them.
An invalid address is skipped and counted, never fatal. An address that is already
suppressed, or appears twice in the request, is counted once. To block a whole domain, use
POST /email-suppressions with "scope": "domain".
Two ways to send addresses. Send JSON with an emails array, as in the example below.
Or upload a CSV file as a form (multipart/form-data) in a field called file, with one
address per row in the first column (a header row is fine):
curl -X POST 'https://app.mailyte.com/api/v1/email-suppressions/import' \
-H 'Authorization: Bearer mk_live_YOUR_API_KEY' \
-F 'file=@unsubscribes.csv' \
-F 'reason=unsubscribed'Send file or emails, not both.
Request body
emailsarray<string>requiredThe addresses to block, 1 to 10,000 per request.
reasonstringOptional. Why they are blocked, shown beside each address in the list, for example
unsubscribedorbounced. Defaults toimport.
Request
/api/v1/email-suppressions/importcurl -X POST 'https://app.mailyte.com/api/v1/email-suppressions/import' \
-H 'Authorization: Bearer mk_live_YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"emails": [
"ada@example.com",
"tunde@example.com"
],
"reason": "unsubscribed"
}'const response = await fetch('https://app.mailyte.com/api/v1/email-suppressions/import', {
method: 'POST',
headers: {
Authorization: 'Bearer mk_live_YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"emails": [
"ada@example.com",
"tunde@example.com"
],
"reason": "unsubscribed"
}),
});
const { data } = await response.json();import requests
response = requests.post(
"https://app.mailyte.com/api/v1/email-suppressions/import",
headers={"Authorization": "Bearer mk_live_YOUR_API_KEY"},
json={
"emails": [
"ada@example.com",
"tunde@example.com"
],
"reason": "unsubscribed"
},
)
data = response.json()["data"]<?php
$response = Http::withToken('mk_live_YOUR_API_KEY')
->post('https://app.mailyte.com/api/v1/email-suppressions/import', [
'emails' => [
'ada@example.com',
'tunde@example.com',
],
'reason' => 'unsubscribed',
]);
$data = $response->json('data');require "net/http"
require "json"
uri = URI("https://app.mailyte.com/api/v1/email-suppressions/import")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer mk_live_YOUR_API_KEY"
request["Content-Type"] = "application/json"
request.body = {
"emails": [
"ada@example.com",
"tunde@example.com"
],
"reason": "unsubscribed"
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }Response
Success.
dataobjectobjectstringsuppression_importimportedintegerAddresses newly suppressed by this call.
skippedobjectTwo causes, one category, and a caller deciding whether to re-upload cares about them very differently.
invalidintegerRows that were not addresses. Your file has typos; a 10,000-row list with three of them imports 9,997. An invalid row is never a rejected request.
duplicateintegerRows already suppressed. Nothing is wrong. Derived from the database's own insert count rather than a pre-check, so it stays exact under a concurrent writer.
totalintegerRows read. Always equal to
imported+skipped.invalid+skipped.duplicate.
Returned inside the standard envelope.
Errors
| Status | When |
|---|---|
401 | The API key is missing, unknown, revoked or expired. All four answer identically, on purpose: distinguishing them would confirm which keys exist. |
403 | The key is valid but may not do this: it lacks the required scope, its IP allowlist does not include you, or this endpoint does not accept API keys. |
404 | No such resource in this organization. |
422 | The request was understood but the values were not acceptable. |
429 | Too many requests, or the organization has spent its sending allowance. `Retry-After` says how long to wait. |
Every status, with what causes it and what to do, is on the error reference.