Hi,
I am trying to send an email using the single-email send api, but I keep getting a 400 Bad Request response. The response body is no help, as it only contains this text: “Invalid request”. I guessed as much from the 400 response…
I find the documentation quite confusing but I gather that I should use the SMTP API token in the Authorization header.
My request looks like this:
https://api.hubapi.com/marketing/v3/transactional/single-email/send
```plaintext
Authorization: Bearer [TOKEN]`
Content-Type: application/json
Accept: application/json
```
And my body looks like this:
```json
{
“emailId”: 123456789012,
“message”: {
"to": "\[REDACTED]"
},
“contactProperties”: {
"firstname": "test",
"lastname": "test"
},
“customProperties”: {
"firstName": "test",
"lastName": "test",
"senderFirstName": "\[REDACTED]",
"senderLastName": "\[REDACTED]",
"clinicName": "\[REDACTED]",
"invitationUrl": "\[REDACTED]",
"invitationToken": "\[REDACTED]"
}
}
```
Happens when a few prerequisites/auth bits are off. Use a Private App token with the transactional-email scope (not the SMTP token) and make sure your account has the Transactional Email add-on, and that the emailId points to a published Transactional email (created in Marketing Email - turn on Transactional). Also, pass every required template token in customProperties with the exact internal names used in the email.
If you still get 400, common causes:
Email is not marked Transactional
Email ID is from a draft or non-published version
A required token in the email isn’t provided (typo in property name) You’re sending to a malformed email
The private app lacks the transactional email scope.
Quick sanity check: open the email’s View details to confirm it’s Published (Transactional) and list the required tokens, then match those names 1:1 in your payload.
Hi,
This is where the documentation is a bit confusing… Some parts tells me to use the SMTP token, others tell me to use the private app token. And since I don’t get a 401 Unauthorized or a 403 Forbidden, when I use the SMTP token, I thought everything is OK.
I will try the Private App token and get back to you.
Why can’t the API tell me these things instead of me having to ask a question about it here? If I make a bad request, as the server tells me, it should tell me exactly why it’s a bad request.
Creating a legacy app and use the token from there seems to have worked.