The Operating System provides services to application programs. These services may include reacting to keyboard input, reacting to mouse input, drawing to the screen, printing to the terminal, reading and writing files, sending and receiving data over the network, and many, many more.
Different Operating Systems offer these services in different ways, using different names for the functions, different parameters, different semantics, and so on. Therefore, an application program needs to be adapted to each OS. This adaptation is typically called "porting" the application.
There are actually two aspects to consider here:
The API is what I mentioned above: the names, types, parameters, and semantics of the various functions that provide the Operating System services.
For example, in Linux, you create a new process with clone, in Windows, you use CreateProcess. In Linux, you open a file with open, in Windows, you use CreateFile.
However, even when Operating Systems have the same API, that does not automatically mean you can run the same binary in both of them. Because even if the names, types, parameters, and semantics of the functions are the same, that does not automatically mean that the encoding of the binary data in memory is the same, or that the way in which arguments are passed is the same. How all of this is encoded in memory and into the CPU is defined by the Application Binary Interface, in other words, that's what the "binary" in "ABI" means. A concrete example of what is defined in the ABI is the so-called calling convention, i.e., how to pass arguments to functions (on the stack, on the heap, in registers, which registers, etc.).
For example, there is the international POSIX standard which defines a portable API for Unix-like Operating Systems: if you write your program using only the functions defined in the POSIX standard, the program should be able to be compiled for every POSIX-compliant OS. But, the program will still have to be compiled for every OS, since they have only the same API but not the same ABI.
In the late 1980s Intel, AT&T, SCO, and some others got together and defined the Intel Binary Compatibility Standard (iBCS), which is an ABI defined for POSIX implementations running on x86. Any program which only uses functions defined in POSIX and is compiled against iBCS will run on every OS that provides an implementation of iBCS. Linux did have an iBCS compatibility layer in the 1990s, but it has long since been removed.
In the 2000, the Linux Standard Base (LSB) was created as an effort to define ABI standards for Linux. The idea was that an application that was compiled against the LSB could be installed and ran on any LSB-compliant Linux distribution. Furthermore, the LSB specification should be precise enough that other Unix-like OS should be able to implement an LSB compatibility layer and thus allow LSB-compliant applications to be used on those OSes as well. However, the LSB was never widely accepted, and the latest release was in 2015.
Nowadays, Linux actually serves the function of such an ABI-compatibility layer. There are multiple Unix-like Operating Systems which can execute Linux programs, for example FreeBSD (Linuxulator), NetBSD (compat_linux), and some of the OpenSolaris forks like OpenIndiana and OmniOS using a feature called Branded Zones.