Skip to main content
Contributor I
October 7, 2026
Question

Bulk Subscribe Profiles: API keeps returning bad request

The error I’m getting is:

"Non-historical email subscription cannot have consented_at timestamp.

If I don’t include consented_at, I don’t get an error but it won’t subscribe the profile either.

Question: if the profile has never been subscribed, why would including the timestamp cause this error?

 

Here’s the URL I’m using:

https://a.klaviyo.com/api/profile-subscription-bulk-create-jobs/

 

Here’s the body I’m using:

{
  "data": {
    "type": "profile-subscription-bulk-create-job",
    "attributes": {
      "profiles": {
        "data": [
          {
            "type": "profile",
            "attributes": {
              "email": "test.email@gmail.com",
              "subscriptions": {
                "email": {
                  "marketing": {
                    "consent": "SUBSCRIBED",
                    "consented_at": "2026-10-02T11:35:21.0480000"
                  }
                }
              }
            }
          }
        ]
      }
    }
  }
}

1 reply

Temi O.
Community Manager
Community Manager
October 15, 2026

Hi there ​@bpgraves , thanks for reaching out! 

The error does not appear to be saying that the profile was previously subscribed. It is describing the type of subscription request you are making.

consented_at is used for a historical subscription import. When Klaviyo sees that field, the request must be marked as historical with historical_import: true. A non-historical subscription represents consent being collected now, so it shouldn’t include consented_at.

For a current subscription, use:

{
"data": {
"type": "profile-subscription-bulk-create-job",
"attributes": {
"profiles": {
"data": [
{
"type": "profile",
"attributes": {
"email": "test.email@gmail.com",
"subscriptions": {
"email": {
"marketing": {
"consent": "SUBSCRIBED"
}
}
}
}
}
]
}
}
}
}

For a genuine historical import, include the flag at the job’s attributes level and use the date on which consent was actually collected:

"attributes": {
"historical_import": true,
"custom_source": "Website consent import",
"profiles": {
"data": [
{
"type": "profile",
"attributes": {
"email": "test.email@gmail.com",
"subscriptions": {
"email": {
"marketing": {
"consent": "SUBSCRIBED",
"consented_at": "2026-10-02T11:35:21.048Z"
}
}
}
}
}
]
}
}

Use an RFC 3339 timestamp with a timezone, like Z or +00:00. Avoid using a made-up historical date. Historical import should only be used when the person gave consent before the import.

If removing consented_at appears not to subscribe the profile, please try checking these points:

  • The POST creates an asynchronous job. Poll the returned job ID until it is complete, then read the profile’s email subscription status.

  • If you associate the job with a list that has double opt-in enabled, the profile may need to confirm the opt-in email before becoming subscribed.

  • Confirm that the email address is correct and that you are checking the same Klaviyo account.

  • If the intent is to collect new consent, use the non-historical request or a Klaviyo sign-up form. Do not use historical import simply to bypass the current-consent flow.

The distinction is therefore: no consented_at for consent collected now; historical_import: true plus a real, correctly formatted consented_at for consent that was collected in the past. More on this here for reference: API guide for collecting email and SMS consent and the bulk subscribe endpoint reference.

Let me know if you have any questions! 

 


Temi@Klaviyo