Skip to main content
Solved

Issue with Square to Klaviyo Integration: Profiles Not Automatically Subscribed


Forum|alt.badge.img

Hello Klaviyo Community,

I’m currently working on integrating Square with Klaviyo, but I'm encountering an issue with subscribing customers to our email and SMS marketing lists automatically.

Issue Overview:

We are using Square to collect customer data, and the goal is to create profiles in Klaviyo with their consent for marketing emails and SMS. However, despite successfully creating the profiles in Klaviyo, the customers are not being automatically subscribed to the email or SMS marketing lists as expected. They are showing as "Email Never Subscribed" in Klaviyo.

What we've tried:

  1. Klaviyo API integration: We've set up a webhook to trigger when a customer is created in Square, which sends the data to Klaviyo. The customer profile is being created successfully, but no subscription status is applied.

  2. Consent for Email/SMS: We’ve ensured that we’re collecting marketing consent for both email and SMS (via the webhook), and we’ve set the consent fields accordingly. However, even with consent provided, the profiles aren't marked as subscribed.

  3. Using Subscribe API: We tried using the API to subscribe the profiles to a list after profile creation, but the subscription doesn't seem to be working, and no confirmation emails/SMS are sent.

  4. List Settings: I have checked that our Klaviyo list is set to single opt-in (we do not want double opt-in) to avoid customers being asked to confirm their subscription.

Challenges:

  • We need a seamless way to ensure that profiles created from Square are automatically subscribed to our Klaviyo lists for both email and SMS marketing, without requiring manual intervention.

  • We're also not sure if there’s a setting or endpoint that needs to be configured differently to ensure the profiles are automatically marked as "subscribed."

Request for Help:

  • Can anyone confirm the correct API endpoints or configuration settings that need to be used to ensure profiles created via Square are automatically subscribed to Klaviyo's email and SMS marketing?

  • Are there any additional steps needed to properly handle marketing consent and subscriptions for profiles created through Square?

Any insights or examples would be greatly appreciated! Thank you for your help.

Best regards,
Dan

Best answer by Byrne C

Hey ​@dannyruss,

Sorry that you’re experiencing issues subscribing profiles! Definitely want to help you get this sorted out.

As a heads-up, I wanted to let you know that since Square is considered an opt-out marketing consent platform, profiles that provide their email in Square are marked in Klaviyo as “Never Subscribed”. That doesn’t mean that you can’t email them - it just means that we can’t be 100% sure that each profile wants to receive emails. Klaviyo won’t stop emails from being sent to these profiles, however. Just make sure that the people you want subscribed know that they’re subscribing to email when they provide their email in Square!

You mention that to get around this issue, you’ve used webhooks to try and subscribe these profiles. What are the names of the specific endpoints you used? Did you use the Bulk Subscribe Profiles API, the Add Profiles to List API, or something else? You may already know this, but the Bulk Subscribe Profiles API is the one you want to use to successfully subscribe profiles to a Klaviyo list.

If you’re already using the Bulk Subscribe Profiles endpoint, the issue here might be related to how you set up the API call. Are you getting error messages returned when these calls are made, or are they coming through successfully? If you’re using a webhook in a Klaviyo flow, you can check that webhook’s activity by clicking on it, and then viewing the details in the tab that pops up on the right. If you’re making these calls from outside of Klaviyo, you can find them in your dev logs here: https://www.klaviyo.com/developer-tools/logs

If you’ve confirmed that you’re successfully sending the correct API call to Klaviyo when a person provides their email in Square, and the call is returning a success message, would you mind sending over a screenshot of one of these calls (with sensitive data redacted)? That will help us investigate it to determine why it’s not subscribing profiles.

-Byrne

View original
Did this topic or the replies in the thread help you find an answer to your question?

4 replies

Byrne C
Community Manager
Forum|alt.badge.img+18
  • Community Manager
  • 207 replies
  • Answer
  • April 8, 2025

Hey ​@dannyruss,

Sorry that you’re experiencing issues subscribing profiles! Definitely want to help you get this sorted out.

As a heads-up, I wanted to let you know that since Square is considered an opt-out marketing consent platform, profiles that provide their email in Square are marked in Klaviyo as “Never Subscribed”. That doesn’t mean that you can’t email them - it just means that we can’t be 100% sure that each profile wants to receive emails. Klaviyo won’t stop emails from being sent to these profiles, however. Just make sure that the people you want subscribed know that they’re subscribing to email when they provide their email in Square!

You mention that to get around this issue, you’ve used webhooks to try and subscribe these profiles. What are the names of the specific endpoints you used? Did you use the Bulk Subscribe Profiles API, the Add Profiles to List API, or something else? You may already know this, but the Bulk Subscribe Profiles API is the one you want to use to successfully subscribe profiles to a Klaviyo list.

If you’re already using the Bulk Subscribe Profiles endpoint, the issue here might be related to how you set up the API call. Are you getting error messages returned when these calls are made, or are they coming through successfully? If you’re using a webhook in a Klaviyo flow, you can check that webhook’s activity by clicking on it, and then viewing the details in the tab that pops up on the right. If you’re making these calls from outside of Klaviyo, you can find them in your dev logs here: https://www.klaviyo.com/developer-tools/logs

If you’ve confirmed that you’re successfully sending the correct API call to Klaviyo when a person provides their email in Square, and the call is returning a success message, would you mind sending over a screenshot of one of these calls (with sensitive data redacted)? That will help us investigate it to determine why it’s not subscribing profiles.

-Byrne


Forum|alt.badge.img
  • Author
  • Contributor I
  • 2 replies
  • April 9, 2025

Hi Byrne,

Thanks so much for your reply and for clarifying the Square opt-out marketing consent situation. I understand that profiles coming from Square are marked as "Never Subscribed" in Klaviyo, and I’ll make sure to manage customer expectations accordingly.

Regarding the issue with subscribing profiles via webhooks, I’ve been using the Bulk Subscribe Profiles API to add profiles to the list, as you suggested. I’ve attached the payload for the API calls and logs below:

  • API Endpoint: POST https://a.klaviyo.com/api/profiles/ (to create a new profile and subscribe them to email and SMS)

  • API Response:{
      "errors": [
        {
          "id": "*************************",
          "status": 400,
          "code": "invalid",
          "title": null,
          "detail": "'marketing_consent' is not a valid field for the resource 'profile'.",
          "source": {
            "pointer": "/data/attributes/profiles/data/0/attributes/marketing_consent"
          },
          "links": {},
          "meta": {}
        }
      ]
    }

  • Error:https://www.klaviyo.com/developer-tools/logs/id/a78e620d-1f27-4f7f-9a1b-4581bab1d994?t=1744178653&callType=api-client

In case the API call isn't working as expected, I’ve also checked the webhook’s activity in the Klaviyo flow. Here are the steps I’ve followed:

  1. Webhook URL: https://www.aimeeprovence.com.au/klaviyo.php

You mentioned checking the dev logs, and I will do that as well. However, if you could kindly guide me on any specific logs or headers to check, it would be very helpful.

Additionally, I’m using the following payload to update the profiles:

{
    "data": {
        "type": "profile",
        "attributes": {
            "email": "service@shop.com",
            "phone_number": "+61420000001",
            "first_name": "John",
            "last_name": "Doe",
            "subscriptions": {
                "email": {
                    "marketing": {
                        "consent": "SUBSCRIBED"
                    }
                },
                "sms": {
                    "marketing": {
                        "consent": "SUBSCRIBED"
                    }
                }
            }
        }
    }
}

 Here’s the code I’ve been using, along with some additional details. Please let me know if I’m missing anything or if the approach needs adjustments.

Code for Webhook Implementation:

<?php

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo 'Method Not Allowed';
    exit;
}

$log_file = __DIR__ . '/debug.txt';
file_put_contents($log_file, "Webhook triggered at " . date('c') . "\n", FILE_APPEND);

$input = file_get_contents('php://input');
$event = json_decode($input, true);
$type = $event['type'] ?? 'undefined';
file_put_contents($log_file, "Event type: $type\n", FILE_APPEND);

// Klaviyo Full Access API key and List ID
$klaviyo_api_key = 'YOUR_API_KEY'; // REPLACE with actual API key
$list_id = '****'; // Your Klaviyo List ID

if ($type === 'customer.created') {
    $customer = $event['data']['object']['customer'];

    $email = $customer['email_address'] ?? null;
    $phone = $customer['phone_number'] ?? null;
    $first_name = $customer['given_name'] ?? null;
    $last_name = $customer['family_name'] ?? null;

    $payload = [
        "data" => [
            "type" => "profile",
            "attributes" => [
                "email" => $email,
                "phone_number" => $phone,
                "first_name" => $first_name,
                "last_name" => $last_name,
                "properties" => [
                    "square_customer_id" => $customer['id'] ?? '',
                    "signup_date" => $customer['created_at'] ?? '',
                    "source" => "Square Signup",
                    "marketing_consent" => "email,sms"
                ]
            ]
        ]
    ];

    file_put_contents($log_file, "Identify payload: " . json_encode($payload, JSON_PRETTY_PRINT) . "\n", FILE_APPEND);

    $ch = curl_init("https://a.klaviyo.com/api/profiles/");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Klaviyo-API-Key ' . $klaviyo_api_key,
        'Content-Type: application/json',
        'revision: 2024-02-15'
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
    $identify_response = curl_exec($ch);
    $identify_http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    file_put_contents($log_file, "New profile response (HTTP $identify_http_code): $identify_response\n", FILE_APPEND);

    $identify_data = json_decode($identify_response, true);
    if (isset($identify_data['errors'][0]['meta']['duplicate_profile_id'])) {
        $profile_id = $identify_data['errors'][0]['meta']['duplicate_profile_id'];
    } elseif (isset($identify_data['data']['id'])) {
        $profile_id = $identify_data['data']['id'];
    } else {
        file_put_contents($log_file, "No profile ID returned, skipping list subscribe.\n", FILE_APPEND);
        http_response_code(200);
        exit;
    }

    // Subscribe profile to list
    $subscribe_payload = [
        "data" => [
            [
                "type" => "profile",
                "id" => $profile_id
            ]
        ]
    ];

    file_put_contents($log_file, "List subscribe payload: " . json_encode($subscribe_payload, JSON_PRETTY_PRINT) . "\n", FILE_APPEND);

    $ch = curl_init("https://a.klaviyo.com/api/lists/$list_id/relationships/profiles/");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Klaviyo-API-Key ' . $klaviyo_api_key,
        'Content-Type: application/json',
        'revision: 2024-02-15'
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($subscribe_payload));
    $subscribe_response = curl_exec($ch);
    $subscribe_http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $subscribe_error = curl_error($ch);
    curl_close($ch);

    file_put_contents($log_file, "List subscribe response (HTTP $subscribe_http_code): $subscribe_response\n", FILE_APPEND);
    if ($subscribe_error) {
        file_put_contents($log_file, "cURL Error: $subscribe_error\n", FILE_APPEND);
    }
}

http_response_code(200);
echo "Webhook complete.\n";

?>

Issues Encountered:

  • The profiles are marked as "Never Subscribed" in Klaviyo, as Square is an opt-out platform.

  • When trying to subscribe profiles via webhooks, I have used the Bulk Subscribe Profiles API, but I am still encountering issues. Specifically, profiles are not being successfully subscribed to email and SMS, even though they are marked with consent ("SUBSCRIBED").

API Responses & Errors:

  • Duplicate Profile Error: I've been receiving HTTP 409 responses, indicating that the profile already exists with the provided identifiers.

  • Invalid Input: On attempts to update profiles or subscribe them, I get HTTP 400 errors related to fields like subscriptions and marketing_consent not being valid for the resource.

If this helps clarify the setup and issues I’m facing, I’d appreciate any further guidance on fixing the subscription process to ensure the profiles are correctly subscribed to both email and SMS.

Thanks again for your help!

 


Byrne C
Community Manager
Forum|alt.badge.img+18
  • Community Manager
  • 207 replies
  • April 10, 2025

@dannyruss,

That’s helpful, thanks!

The 400 request you’re seeing suggests that your call is structured incorrectly, and from what you sent above, it does look as if it could use some re-structuring. Make sure that you’re calling the the right revision (the most updated v2025-01-15 revision) and you’re using this format below:

curl --request POST \
     --url https://a.klaviyo.com/api/profile-subscription-bulk-create-jobs \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/vnd.api+json' \
     --header 'content-type: application/vnd.api+json' \
     --header 'revision: 2025-01-15' \
     --data '
{
  "data": {
    "type": "profile-subscription-bulk-create-job",
    "attributes": {
      "profiles": {
        "data": [
          {
            "type": "profile",
            "attributes": {
              "subscriptions": {
                "email": {
                  "marketing": {
                    "consent": "SUBSCRIBED"
                  }
                },
                "sms": {
                  "marketing": {
                    "consent": "SUBSCRIBED"
                  },
                  "transactional": {
                    "consent": "SUBSCRIBED"
                  }
                }
              },
              "email": "test@test.com",
              "phone_number": "+15555555"
            }
          }
        ]
      },
      "historical_import": false
    },
    "relationships": {
      "list": {
        "data": {
          "type": "list",
          "id": "LIST_ID_HERE"
        }
      }
    }
  }
}
'

The info in red is what you should replace with info specific to your account.

For checking the dev logs, it doesn’t appear that your headers are the issue, as you’re not getting any errors related to permissions or authorization. I’d always recommend checking the structure of your call to see if it matches the structure of the call shown in the developer portal page: https://developers.klaviyo.com/en/reference/bulk_subscribe_profiles. In your case, I noticed some differences in structure, so I’d recommend following the structure above. 

Let me know if this works!

-Byrne


Forum|alt.badge.img
  • Author
  • Contributor I
  • 2 replies
  • April 14, 2025

Hi Byrne,

 

Thanks again for your help—I managed to get the request working with the correct structure, which is great!

 

However, I’ve now run into a new issue. When customers sign up in-store, they often only provide their phone number (no email at that stage), which is fine from a Square perspective. My intention is to use a conditional Klaviyo flow to follow up and collect their email address and full details later.

 

The problem is that Klaviyo’s SMS subscription seems to fail if the customer doesn’t already have both an email and phone number at the time of initial subscription. In other words, the SMS marketing consent doesn’t go through unless both fields are present upfront.

 

Is there any workaround you’d recommend for this? For example, is it possible to subscribe a profile to SMS-only marketing with just a phone number, and then update the profile later with the email address when it’s provided?

 

Would really appreciate any advice or best practices on handling this kind of gradual data capture.

 

Thanks again!

Daniel


Reply