You can avoid the union if you just have the uint16_t data type (let's keep it prebufferk), and when you call USBD_HID_SendReport(&hUsbDeviceHS, bufferk, 8 );, you cast it to a uint8_t * like someone else pointed out earlier in the thread. Since it looks like the call takes a pointer to the data buffer and number of bytes, you could just do:
USBD_HID_SendReport(&hUsbDeviceHS, (uint8_t *)prebufferk, 8);
Assuming the part where you're reading from the SPI register and indexing is working correctly, this should work fine. And even better:
USBD_HID_SendReport(&hUsbDeviceHS, (uint8_t *)prebufferk, sizeof(prebufferk));
When you pass a pointer to a function, you're essentially passing the memory address of the first element in the allocated memory block. You've allocated 4 uint16_t's in memory (uint16_t prebufferk[4]; ). Which is the same as 8 uint8_t's if you envision it in the memory stack. You can safely cast it to a uint8_t * and tell the function to read out 8 bytes.
You use sizeof() so if you change the size of the prebufferk and all the calls still work; you don't have to go through everything and change the "8" to something else. And again, since prebufferk is an array of 4 uint16_t's, sizeof(prebufferk) is 2 bytes * 4 elements = 8.