Pular para o conteúdo principal
Todo evento chega com a mesma casca:
O entry[].id é o user_id da conta profissional, o mesmo devolvido por Dados da conta. Use-o para saber a qual canal o evento pertence.
O entry[].id não é o id que GET /ig/me devolve no campo id. São valores diferentes, e só o user_id casa com o webhook.

Duas formas dentro do mesmo envelope

O conteúdo vem em uma de duas listas, e elas se comportam de maneiras diferentes: Em changes[] basta ler field. Em messaging[] é preciso testar quais chaves existem:

A unidade de entry.time muda

O entry[].time vem em milissegundos quando o evento está em messaging[], e em segundos quando está em changes[].
Tratar os dois como a mesma unidade coloca comentários em 1970 ou mensagens em um futuro distante. Normalize antes de guardar:
Dentro de messaging[], o campo timestamp do próprio evento é sempre em milissegundos e costuma ser mais preciso que o time do entry.

Um envio pode trazer vários eventos

A lista entry[] aceita mais de um item, e cada item aceita vários eventos. Percorra as listas em vez de ler apenas o primeiro elemento.