diff --git a/paper-api/src/main/java/org/bukkit/block/Sign.java b/paper-api/src/main/java/org/bukkit/block/Sign.java
index ab6b0ec328..89c08d31d2 100644
--- a/paper-api/src/main/java/org/bukkit/block/Sign.java
+++ b/paper-api/src/main/java/org/bukkit/block/Sign.java
@@ -1,31 +1,38 @@
 package org.bukkit.block;
 
-import org.bukkit.material.Colorable;
+import org.bukkit.block.sign.Side;
+import org.bukkit.block.sign.SignSide;
 import org.jetbrains.annotations.NotNull;
 
 /**
  * Represents a captured state of either a SignPost or a WallSign.
  */
-public interface Sign extends TileState, Colorable {
+public interface Sign extends SignSide, TileState {
 
     /**
-     * Gets all the lines of text currently on this sign.
+     * Gets all the lines of text currently on the {@link Side#FRONT} of this sign.
      *
      * @return Array of Strings containing each line of text
+     * @deprecated  A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#getLines()}.
      */
+    @Deprecated
     @NotNull
+    @Override
     public String[] getLines();
 
     /**
      * Gets the line of text at the specified index.
      * <p>
-     * For example, getLine(0) will return the first line of text.
+     * For example, getLine(0) will return the first line of text on the {@link Side#FRONT}.
      *
      * @param index Line number to get the text from, starting at 0
      * @return Text on the given line
      * @throws IndexOutOfBoundsException Thrown when the line does not exist
+     * @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#getLine(int)}.
      */
+    @Deprecated
     @NotNull
+    @Override
     public String getLine(int index) throws IndexOutOfBoundsException;
 
     /**
@@ -37,7 +44,10 @@ public interface Sign extends TileState, Colorable {
      * @param index Line number to set the text at, starting from 0
      * @param line New text to set at the specified index
      * @throws IndexOutOfBoundsException If the index is out of the range 0..3
+     * @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#setLine(int, String)}.
      */
+    @Deprecated
+    @Override
     public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException;
 
     /**
@@ -63,16 +73,31 @@ public interface Sign extends TileState, Colorable {
     public void setEditable(boolean editable);
 
     /**
-     * Gets whether this sign has glowing text.
+     * Gets whether this sign has glowing text. Only affects the {@link Side#FRONT}.
      *
      * @return if this sign has glowing text
+     * @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#isGlowingText()}.
      */
+    @Deprecated
+    @Override
     public boolean isGlowingText();
 
     /**
-     * Sets whether this sign has glowing text.
+     * Sets whether this sign has glowing text. Only affects the {@link Side#FRONT}.
      *
      * @param glowing if this sign has glowing text
+     * @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#setGlowingText(boolean)}.
      */
+    @Deprecated
+    @Override
     public void setGlowingText(boolean glowing);
+
+    /**
+     * Return the side of the sign.
+     *
+     * @param side the side of the sign
+     * @return the selected side of the sign
+     */
+    @NotNull
+    public SignSide getSide(@NotNull Side side);
 }
diff --git a/paper-api/src/main/java/org/bukkit/block/sign/Side.java b/paper-api/src/main/java/org/bukkit/block/sign/Side.java
new file mode 100644
index 0000000000..5abe260f70
--- /dev/null
+++ b/paper-api/src/main/java/org/bukkit/block/sign/Side.java
@@ -0,0 +1,9 @@
+package org.bukkit.block.sign;
+
+/**
+ * Represents the side of sign.
+ */
+public enum Side {
+
+    FRONT,
+}
diff --git a/paper-api/src/main/java/org/bukkit/block/sign/SignSide.java b/paper-api/src/main/java/org/bukkit/block/sign/SignSide.java
new file mode 100644
index 0000000000..0f4ae7bd2a
--- /dev/null
+++ b/paper-api/src/main/java/org/bukkit/block/sign/SignSide.java
@@ -0,0 +1,56 @@
+package org.bukkit.block.sign;
+
+import org.bukkit.material.Colorable;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Represents a side of a sign.
+ */
+public interface SignSide extends Colorable {
+
+    /**
+     * Gets all the lines of text currently on this side of the sign.
+     *
+     * @return Array of Strings containing each line of text
+     */
+    @NotNull
+    public String[] getLines();
+
+    /**
+     * Gets the line of text at the specified index on this side of the sign.
+     * <p>
+     * For example, getLine(0) will return the first line of text.
+     *
+     * @param index Line number to get the text from, starting at 0
+     * @return Text on the given line
+     * @throws IndexOutOfBoundsException Thrown when the line does not exist
+     */
+    @NotNull
+    public String getLine(int index) throws IndexOutOfBoundsException;
+
+    /**
+     * Sets the line of text at the specified index on this side of the sign.
+     * <p>
+     * For example, setLine(0, "Line One") will set the first line of text to
+     * "Line One".
+     *
+     * @param index Line number to set the text at, starting from 0
+     * @param line New text to set at the specified index
+     * @throws IndexOutOfBoundsException If the index is out of the range 0..3
+     */
+    public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException;
+
+    /**
+     * Gets whether this side of the sign has glowing text.
+     *
+     * @return if this side of the sign has glowing text
+     */
+    public boolean isGlowingText();
+
+    /**
+     * Sets whether this side of the sign has glowing text.
+     *
+     * @param glowing if this side of the sign has glowing text
+     */
+    public void setGlowingText(boolean glowing);
+}
diff --git a/paper-api/src/main/java/org/bukkit/block/sign/package-info.java b/paper-api/src/main/java/org/bukkit/block/sign/package-info.java
new file mode 100644
index 0000000000..5d3cc62204
--- /dev/null
+++ b/paper-api/src/main/java/org/bukkit/block/sign/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Classes relevant to signs.
+ */
+package org.bukkit.block.sign;
diff --git a/paper-api/src/main/java/org/bukkit/entity/Player.java b/paper-api/src/main/java/org/bukkit/entity/Player.java
index b4ef6cd992..b768b066db 100644
--- a/paper-api/src/main/java/org/bukkit/entity/Player.java
+++ b/paper-api/src/main/java/org/bukkit/entity/Player.java
@@ -23,6 +23,7 @@ import org.bukkit.block.Block;
 import org.bukkit.block.BlockState;
 import org.bukkit.block.Sign;
 import org.bukkit.block.data.BlockData;
+import org.bukkit.block.sign.Side;
 import org.bukkit.conversations.Conversable;
 import org.bukkit.event.block.BlockBreakEvent;
 import org.bukkit.event.block.BlockDropItemEvent;
@@ -1720,6 +1721,16 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
      */
     public void openSign(@NotNull Sign sign);
 
+    /**
+     * Open a Sign for editing by the Player.
+     *
+     * The Sign must be placed in the same world as the player.
+     *
+     * @param sign The sign to edit
+     * @param side The side to edit
+     */
+    public void openSign(@NotNull Sign sign, @NotNull Side side);
+
     /**
      * Shows the demo screen to the player, this screen is normally only seen in
      * the demo version of the game.
diff --git a/paper-api/src/main/java/org/bukkit/event/block/SignChangeEvent.java b/paper-api/src/main/java/org/bukkit/event/block/SignChangeEvent.java
index 7190db11ef..f4ac033ff8 100644
--- a/paper-api/src/main/java/org/bukkit/event/block/SignChangeEvent.java
+++ b/paper-api/src/main/java/org/bukkit/event/block/SignChangeEvent.java
@@ -1,6 +1,7 @@
 package org.bukkit.event.block;
 
 import org.bukkit.block.Block;
+import org.bukkit.block.sign.Side;
 import org.bukkit.entity.Player;
 import org.bukkit.event.Cancellable;
 import org.bukkit.event.HandlerList;
@@ -17,11 +18,18 @@ public class SignChangeEvent extends BlockEvent implements Cancellable {
     private boolean cancel = false;
     private final Player player;
     private final String[] lines;
+    private final Side side;
 
+    @Deprecated
     public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player thePlayer, @NotNull final String[] theLines) {
+        this(theBlock, thePlayer, theLines, Side.FRONT);
+    }
+
+    public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player thePlayer, @NotNull final String[] theLines, @NotNull Side side) {
         super(theBlock);
         this.player = thePlayer;
         this.lines = theLines;
+        this.side = side;
     }
 
     /**
@@ -70,6 +78,16 @@ public class SignChangeEvent extends BlockEvent implements Cancellable {
         lines[index] = line;
     }
 
+    /**
+     * Returns which side is changed.
+     *
+     * @return the affected side of the sign
+     */
+    @NotNull
+    public Side getSide() {
+        return side;
+    }
+
     @Override
     public boolean isCancelled() {
         return cancel;