SingleMail
TRLog in

API reference

Every request goes to https://api.singlemail.singleton.com.tr with an Authorization: Bearer sm_… header. Bodies and responses are JSON.

Sending an email

POST /emails
{
  "from": "Destek <destek@firma.com>",
  "to": ["ali@ornek.com"],
  "subject": "Talebiniz alındı",
  "html": "<p>…</p>",
  "tags": [{ "name": "type", "value": "ticket" }]
}

→ 200 { "id": "abe55c23-533d-41ad-8971-2dad84ad985b" }
FieldTypeDescription
fromstringA single sender: "address@domain" or "Name <address@domain>". The name may not contain @ , ; : < > "; the domain must be verified.
tostring | string[]Recipient(s).
subjectstringSubject.
html / textstringAt least one is required.
cc / bcc / reply_tostring | string[]Optional.
headersobjectUp to 20 custom headers: List-Unsubscribe(-Post), In-Reply-To, References, X-*. Address and routing headers such as From, Sender, Bcc are rejected.
tags{name, value}[]Labels returned in webhooks, useful for filtering.
attachments{filename, content | path, content_type, content_id}[]content is base64, or path a public URL (fetched by SingleMail, max 10 MB). content_id for inline images.
scheduled_atstringISO date or "in 10 minutes".

Emails

MethodPathDescription
POST/emailsSends an email. Supports the Idempotency-Key header.
POST/emails/batchSends up to 100 emails in one request.
GET/emailsLists sent emails (?limit, ?after).
GET/emails/:idReturns a single email and its status.
GET/emails/:id/eventsEvent history of an email.
PATCH/emails/:idReschedules a scheduled email.
POST/emails/:id/cancelCancels a scheduled email.

Domains

MethodPathDescription
POST/domainsAdds a domain and returns its DNS records.
GET/domainsLists domains.
GET/domains/:idA domain and its DNS records.
PATCH/domains/:idTurns open/click tracking on or off.
POST/domains/:id/verifyChecks the DNS records.
DELETE/domains/:idDeletes the domain.

API keys

MethodPathDescription
POST/api-keysCreates a key (full_access or sending_access).
GET/api-keysLists keys.
DELETE/api-keys/:idRevokes a key.

Webhooks

MethodPathDescription
POST/webhooksAdds a webhook and returns its signing secret (whsec_…).
GET/webhooksLists webhooks.
GET/webhooks/:idA webhook and its signing secret.
PATCH/webhooks/:idUpdates endpoint, events or status.
DELETE/webhooks/:idDeletes a webhook.

Suppressions

MethodPathDescription
POST/suppressionsAdds an address to the suppression list.
GET/suppressionsLists suppressed addresses.
DELETE/suppressions/:idOrEmailRemoves an address from the list.

Pagination

List endpoints return { object: "list", has_more, data }. Use ?limit= (max 100) and ?after= with the last ID of the previous page.

Errors

Failed requests return: { statusCode, name, message }

CodenameMeaning
401missing_api_keyNo Authorization header.
401restricted_api_keyA sending-only key called a management endpoint.
401restricted_api_keyA sending-only key tried to read or cancel emails.
403invalid_api_keyInvalid API key.
429rate_limit_exceeded30 invalid keys from one IP; wait 10 minutes.
403project_suspendedThe project or company was suspended by an administrator.
403sending_pausedSending was paused because of a high bounce or complaint rate; your administrator reviews and resumes it.
403plan_limit_reachedYour plan's domain or project limit is reached.
403validation_errorDomain is not registered or not verified.
404not_foundResource not found.
409concurrent_idempotent_requestsThe first request with this key is still running.
422validation_errorInvalid body; the message names the field.
422content_rejectedThe content looks like spam; score and reasons in the response say why.
422phishing_suspectedContains a form, script, javascript: link or a link to an IP address.
422attachment_rejectedExecutable or macro-enabled attachment.
422recipient_rejectedDisposable, misspelled or non-receiving recipient domain.
422blocklistedA keyword or domain on the platform blocklist.
429rate_limit_exceededPer-second request limit exceeded.
429monthly_quota_exceededYour plan's monthly sending limit is used up; it resets on the 1st (UTC).
429warmup_limit_exceededNew accounts can reach a limited number of recipients per hour at first.
429daily_quota_exceededThe plan's or project's daily limit is used up; it resets at midnight UTC.

Protection errors

When spam and abuse protection rejects a send, the response also names the check and the reasons. A blocked send isn't stored and doesn't count against your quota. In a batch, if one email is rejected none are sent; the message starts with the index, e.g. [3].

422
{
  "statusCode": 422,
  "name": "content_rejected",
  "message": "Email content looks like spam (score 9.5): …",
  "check": "content",
  "score": 9.5,
  "reasons": [
    "Spam phrases: kazandiniz, hemen tikla (+3)",
    "Subject is in capital letters (+1.5)",
    "Uses a link shortener (+2)"
  ],
  "details": [
    { "code": "spam_phrases", "params": { "phrases": "kazandiniz, hemen tikla", "points": 3 } },
    { "code": "spam_subject_caps", "params": { "points": 1.5 } },
    { "code": "spam_shortener", "params": { "points": 2 } }
  ]
}

reasons is English text and may change. To show the reason in your own UI or to branch on it, use details, which lists the same reasons in the same order as a stable code plus params. The possible codes:

codecheckparamsExample
reputation_bounce_ratereputationrate, limitBounce rate 7.4% in the last 24 hours (limit 5.0%)
reputation_complaint_ratereputationrate, limitSpam complaint rate 0.42% in the last 24 hours (limit 0.30%)
reputation_pausedreputation—Paused by the reputation guard
reputation_review_requiredreputation—An administrator must review and resume the project
warmup_limitwarmuphourly, daysNew accounts can reach 300 recipients per hour during the first 7 days
recipient_disposablerecipientsrecipient, domainkisi@mailinator.com: disposable email address
recipient_typorecipientsrecipient, domain, suggestionahmet@gmial.com: looks like a typo, did you mean @gmail.com?
recipient_reservedrecipientsrecipient, domaintest@example.com: reserved test domain that can't receive mail
recipient_no_mxrecipientsrecipient, domaininfo@firma-yok.com.tr: the domain firma-yok.com.tr has no mail server
blocklist_keywordblocklistkeywordContains a blocked keyword ("deneme bonusu")
blocklist_link_domainblocklistdomainLinks to a blocked domain (kumar-sitesi.example)
blocklist_recipient_domainblocklistdomainRecipient domain is blocked (rakip.example)
blocklist_sender_domainblocklistdomainSender domain is blocked (kumar-sitesi.example)
attachment_extensionattachmentsfilename, extAttachment "fatura.pdf.exe" has a blocked file type (.exe)
attachment_content_typeattachmentsfilename, contentTypeAttachment "kurulum" has a blocked content type (application/x-msdownload)
phishing_formphishing—Contains an HTML form (emails must not collect input)
phishing_scriptphishing—Contains script, iframe or embedded objects
phishing_event_handlerphishing—Contains inline JavaScript event handlers
phishing_js_linkphishing—Contains a javascript:/data: link
phishing_userinfophishinghostLink hides its real destination with user@host (evil.example.net)
phishing_ip_linkphishinghostLinks to a bare IP address (185.12.4.9)
spam_phrasescontentphrases, pointsSpam phrases: kazandiniz, hemen tikla (+3)
spam_subject_capscontentpointsSubject is in capital letters (+1.5)
spam_subject_exclamationcontentpointsToo many exclamation marks in the subject (+1)
spam_money_symbolscontentpointsMoney symbols ($$$) (+1)
spam_shortenercontentpointsUses a link shortener (+2)
spam_punycodecontentpointsLinks to a punycode (look-alike) domain (+1.5)
spam_link_mismatchcontenthost, pointsLink text shows one domain but points to another (secure-login.example.net) (+3)
spam_many_linkscontentpointsVery many links (+1)
spam_lurecontentpointsAccount or payment lure linking to another domain (+2.5)
spam_image_onlycontentpointsImage-only email without text (+2)

Using your own full-length links, not writing subjects in capitals and not showing another domain in link text avoids most content rejections. If you think a rejection is wrong, talk to your SingleMail administrator; they can adjust the check for your account.