diff --git a/src/main/java/org/qora/api/resource/NamesResource.java b/src/main/java/org/qora/api/resource/NamesResource.java
index fde7429a..2df4a501 100644
--- a/src/main/java/org/qora/api/resource/NamesResource.java
+++ b/src/main/java/org/qora/api/resource/NamesResource.java
@@ -28,7 +28,10 @@ import org.qora.api.ApiExceptionFactory;
 import org.qora.api.model.NameSummary;
 import org.qora.crypto.Crypto;
 import org.qora.data.naming.NameData;
+import org.qora.data.transaction.BuyNameTransactionData;
+import org.qora.data.transaction.CancelSellNameTransactionData;
 import org.qora.data.transaction.RegisterNameTransactionData;
+import org.qora.data.transaction.SellNameTransactionData;
 import org.qora.data.transaction.UpdateNameTransactionData;
 import org.qora.repository.DataException;
 import org.qora.repository.Repository;
@@ -36,7 +39,10 @@ import org.qora.repository.RepositoryManager;
 import org.qora.transaction.Transaction;
 import org.qora.transaction.Transaction.ValidationResult;
 import org.qora.transform.TransformationException;
+import org.qora.transform.transaction.BuyNameTransactionTransformer;
+import org.qora.transform.transaction.CancelSellNameTransactionTransformer;
 import org.qora.transform.transaction.RegisterNameTransactionTransformer;
+import org.qora.transform.transaction.SellNameTransactionTransformer;
 import org.qora.transform.transaction.UpdateNameTransactionTransformer;
 import org.qora.utils.Base58;
 
@@ -215,4 +221,133 @@ public class NamesResource {
 		}
 	}
 
+	@POST
+	@Path("/sell")
+	@Operation(
+		summary = "Build raw, unsigned, SELL_NAME transaction",
+		requestBody = @RequestBody(
+			required = true,
+			content = @Content(
+				mediaType = MediaType.APPLICATION_JSON,
+				schema = @Schema(
+					implementation = SellNameTransactionData.class
+				)
+			)
+		),
+		responses = {
+			@ApiResponse(
+				description = "raw, unsigned, SELL_NAME transaction encoded in Base58",
+				content = @Content(
+					mediaType = MediaType.TEXT_PLAIN,
+					schema = @Schema(
+						type = "string"
+					)
+				)
+			)
+		}
+	)
+	@ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
+	public String sellName(SellNameTransactionData transactionData) {
+		try (final Repository repository = RepositoryManager.getRepository()) {
+			Transaction transaction = Transaction.fromData(repository, transactionData);
+
+			ValidationResult result = transaction.isValidUnconfirmed();
+			if (result != ValidationResult.OK)
+				throw TransactionsResource.createTransactionInvalidException(request, result);
+
+			byte[] bytes = SellNameTransactionTransformer.toBytes(transactionData);
+			return Base58.encode(bytes);
+		} catch (TransformationException e) {
+			throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
+		} catch (DataException e) {
+			throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
+		}
+	}
+
+	@POST
+	@Path("/sell/cancel")
+	@Operation(
+		summary = "Build raw, unsigned, CANCEL_SELL_NAME transaction",
+		requestBody = @RequestBody(
+			required = true,
+			content = @Content(
+				mediaType = MediaType.APPLICATION_JSON,
+				schema = @Schema(
+					implementation = CancelSellNameTransactionData.class
+				)
+			)
+		),
+		responses = {
+			@ApiResponse(
+				description = "raw, unsigned, CANCEL_SELL_NAME transaction encoded in Base58",
+				content = @Content(
+					mediaType = MediaType.TEXT_PLAIN,
+					schema = @Schema(
+						type = "string"
+					)
+				)
+			)
+		}
+	)
+	@ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
+	public String cancelSellName(CancelSellNameTransactionData transactionData) {
+		try (final Repository repository = RepositoryManager.getRepository()) {
+			Transaction transaction = Transaction.fromData(repository, transactionData);
+
+			ValidationResult result = transaction.isValidUnconfirmed();
+			if (result != ValidationResult.OK)
+				throw TransactionsResource.createTransactionInvalidException(request, result);
+
+			byte[] bytes = CancelSellNameTransactionTransformer.toBytes(transactionData);
+			return Base58.encode(bytes);
+		} catch (TransformationException e) {
+			throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
+		} catch (DataException e) {
+			throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
+		}
+	}
+
+	@POST
+	@Path("/buy")
+	@Operation(
+		summary = "Build raw, unsigned, BUY_NAME transaction",
+		requestBody = @RequestBody(
+			required = true,
+			content = @Content(
+				mediaType = MediaType.APPLICATION_JSON,
+				schema = @Schema(
+					implementation = BuyNameTransactionData.class
+				)
+			)
+		),
+		responses = {
+			@ApiResponse(
+				description = "raw, unsigned, BUY_NAME transaction encoded in Base58",
+				content = @Content(
+					mediaType = MediaType.TEXT_PLAIN,
+					schema = @Schema(
+						type = "string"
+					)
+				)
+			)
+		}
+	)
+	@ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
+	public String buyName(BuyNameTransactionData transactionData) {
+		try (final Repository repository = RepositoryManager.getRepository()) {
+			Transaction transaction = Transaction.fromData(repository, transactionData);
+
+			ValidationResult result = transaction.isValidUnconfirmed();
+			if (result != ValidationResult.OK)
+				throw TransactionsResource.createTransactionInvalidException(request, result);
+
+			byte[] bytes = BuyNameTransactionTransformer.toBytes(transactionData);
+			return Base58.encode(bytes);
+		} catch (TransformationException e) {
+			throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
+		} catch (DataException e) {
+			throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
+		}
+	}
+
 }
\ No newline at end of file
diff --git a/src/main/java/org/qora/data/transaction/BuyNameTransactionData.java b/src/main/java/org/qora/data/transaction/BuyNameTransactionData.java
index 743c895e..27bde460 100644
--- a/src/main/java/org/qora/data/transaction/BuyNameTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/BuyNameTransactionData.java
@@ -4,6 +4,8 @@ import java.math.BigDecimal;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
 import org.qora.transaction.Transaction.TransactionType;
 
@@ -15,16 +17,28 @@ import io.swagger.v3.oas.annotations.media.Schema;
 public class BuyNameTransactionData extends TransactionData {
 
 	// Properties
+	@Schema(description = "buyer's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
 	private byte[] buyerPublicKey;
+	@Schema(description = "which name to buy", example = "my-name")
 	private String name;
+	@Schema(description = "selling price", example = "123.456")
+	@XmlJavaTypeAdapter(
+		type = BigDecimal.class,
+		value = org.qora.api.BigDecimalTypeAdapter.class
+	)
 	private BigDecimal amount;
+	@Schema(description = "seller's address", example = "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v")
 	private String seller;
+	// For internal use when orphaning
+	@XmlTransient
+	@Schema(hidden = true)
 	private byte[] nameReference;
 
 	// Constructors
 
 	// For JAX-RS
 	protected BuyNameTransactionData() {
+		super(TransactionType.BUY_NAME);
 	}
 
 	public BuyNameTransactionData(byte[] buyerPublicKey, String name, BigDecimal amount, String seller, byte[] nameReference, BigDecimal fee, long timestamp,
diff --git a/src/main/java/org/qora/data/transaction/CancelSellNameTransactionData.java b/src/main/java/org/qora/data/transaction/CancelSellNameTransactionData.java
index 02f650f5..e55da8c9 100644
--- a/src/main/java/org/qora/data/transaction/CancelSellNameTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/CancelSellNameTransactionData.java
@@ -15,13 +15,16 @@ import io.swagger.v3.oas.annotations.media.Schema;
 public class CancelSellNameTransactionData extends TransactionData {
 
 	// Properties
+	@Schema(description = "owner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
 	private byte[] ownerPublicKey;
+	@Schema(description = "which name to cancel selling", example = "my-name")
 	private String name;
 
 	// Constructors
 
 	// For JAX-RS
 	protected CancelSellNameTransactionData() {
+		super(TransactionType.CANCEL_SELL_NAME);
 	}
 
 	public CancelSellNameTransactionData(byte[] ownerPublicKey, String name, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
diff --git a/src/main/java/org/qora/data/transaction/SellNameTransactionData.java b/src/main/java/org/qora/data/transaction/SellNameTransactionData.java
index c68e66b0..e7f9cef7 100644
--- a/src/main/java/org/qora/data/transaction/SellNameTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/SellNameTransactionData.java
@@ -4,6 +4,7 @@ import java.math.BigDecimal;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
 import org.qora.transaction.Transaction.TransactionType;
 
@@ -15,14 +16,22 @@ import io.swagger.v3.oas.annotations.media.Schema;
 public class SellNameTransactionData extends TransactionData {
 
 	// Properties
+	@Schema(description = "owner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
 	private byte[] ownerPublicKey;
+	@Schema(description = "which name to sell", example = "my-name")
 	private String name;
+	@Schema(description = "selling price", example = "123.456")
+	@XmlJavaTypeAdapter(
+		type = BigDecimal.class,
+		value = org.qora.api.BigDecimalTypeAdapter.class
+	)
 	private BigDecimal amount;
 
 	// Constructors
 
 	// For JAX-RS
 	protected SellNameTransactionData() {
+		super(TransactionType.SELL_NAME);
 	}
 
 	public SellNameTransactionData(byte[] ownerPublicKey, String name, BigDecimal amount, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
diff --git a/src/main/java/org/qora/transaction/BuyNameTransaction.java b/src/main/java/org/qora/transaction/BuyNameTransaction.java
index c8c57d55..8858bafd 100644
--- a/src/main/java/org/qora/transaction/BuyNameTransaction.java
+++ b/src/main/java/org/qora/transaction/BuyNameTransaction.java
@@ -28,6 +28,10 @@ public class BuyNameTransaction extends Transaction {
 		super(repository, transactionData);
 
 		this.buyNameTransactionData = (BuyNameTransactionData) this.transactionData;
+
+		// XXX This is horrible - thanks to JAXB unmarshalling not calling constructor
+		if (this.transactionData.getCreatorPublicKey() == null)
+			this.transactionData.setCreatorPublicKey(this.buyNameTransactionData.getBuyerPublicKey());
 	}
 
 	// More information
diff --git a/src/main/java/org/qora/transaction/CancelSellNameTransaction.java b/src/main/java/org/qora/transaction/CancelSellNameTransaction.java
index 9492d6f5..d5ba488b 100644
--- a/src/main/java/org/qora/transaction/CancelSellNameTransaction.java
+++ b/src/main/java/org/qora/transaction/CancelSellNameTransaction.java
@@ -28,6 +28,10 @@ public class CancelSellNameTransaction extends Transaction {
 		super(repository, transactionData);
 
 		this.cancelSellNameTransactionData = (CancelSellNameTransactionData) this.transactionData;
+
+		// XXX This is horrible - thanks to JAXB unmarshalling not calling constructor
+		if (this.transactionData.getCreatorPublicKey() == null)
+			this.transactionData.setCreatorPublicKey(this.cancelSellNameTransactionData.getOwnerPublicKey());
 	}
 
 	// More information
diff --git a/src/main/java/org/qora/transaction/SellNameTransaction.java b/src/main/java/org/qora/transaction/SellNameTransaction.java
index ac3b01b3..4b18332a 100644
--- a/src/main/java/org/qora/transaction/SellNameTransaction.java
+++ b/src/main/java/org/qora/transaction/SellNameTransaction.java
@@ -29,6 +29,10 @@ public class SellNameTransaction extends Transaction {
 		super(repository, transactionData);
 
 		this.sellNameTransactionData = (SellNameTransactionData) this.transactionData;
+
+		// XXX This is horrible - thanks to JAXB unmarshalling not calling constructor
+		if (this.transactionData.getCreatorPublicKey() == null)
+			this.transactionData.setCreatorPublicKey(this.sellNameTransactionData.getOwnerPublicKey());
 	}
 
 	// More information