Set States API error

You were really close! There are two mistakes, the first is that you should send the right Content-Type header so that the server knows how to read the data. So just change your headers variable to be:

$headers = array(
    'Authorization: Bearer ' . $authToken,
    'Content-Type: application/json'
);

The second problem is that you have included the selector wrong. The selector needs to be a string in the selector attribute. Like this:

{
  "selector":"id:dxxxxxxxxxe2",
  "brightness":0.75,
  "kelvin":"2700",
  "duration":null
},

So here is a working example, based off yours. Do you mind if I add this to the official documentation?

<?php

$authToken = "[YOUR TOKEN HERE]";

$data = array(
    "states" => array(
        array(
            "selector" => "id:d073d501b1e5",
            "brightness" => 0.1,
            "kelvin" => 2700,
        ),
        array(
            "selector" => "id:d073d503a4c1",
            "brightness" => 0.75,
            "kelvin" => 2700,
        )
    ),
    "defaults" => array(
        "duration" => 300,
    )
);

$link = "https://api.lifx.com/v1/lights/states";
$headers = array(
    'Authorization: Bearer ' . $authToken,
    'Content-Type: application/json'
);
$ch = curl_init($link);

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");

$response = curl_exec($ch);

?>