As you want to "trigger only when ... changes ...", you need to set data only if these changes happen.
Here you need to implement dataHasChanged( data ) according to your needs (you didn't specify what "API change" means exactly).
const [ data, setData ] = useState([]);
useEffect(() => {
  fetch( /*...*/ )
    .then(( data ) => {
      if( dataHasChanged( data ) ){  // <----- only set data if necessary
        setData( data );
      }
    });
}, [ data ]);
Alternatively (if appropriate for your use case), you might only fetch the new data if you know it might have changed:
const [ data, setData ] = useState([]);
useEffect(() => {
  if( !newDataNeedsToBeFetched( data ) ){ // <----- skip if no fetch necessary
    return;
  }
  fetch( /* ... */ )
    .then(( data ) => {
      setData( data );
    });
}, [ data ]);
implement hasChanged()
How to determine if data has changed in javascript is a separate question. Maybe you even don't have a problem there, otherwise please refer to other answers about that, e.g. design-pattern-to-check-if-a-javascript-object-has-changed.
You might also want to know about using useRef() to store the previous value: how-to-compare-oldvalues-and-newvalues-on-react-hooks-useeffect