The Bitcoin Dojo

Welcome to the UTXO Dojo! You can use this API to do just about anything you can imagine with Bitcoin, and there are also libraries available that make it easier to use (more on that momentarily).

Register new Paymail handles and manage Bitcoins easily with nothing other than a private key. Plug it into your existing application, and never worry about change outputs or address re-use again.

Read through these docs, and if you still have questions, we're happy to answer them on Slack.

Happy hacking, and if you built something cool, we'd love to hear about it :)

Initial Setup

You can use the UTXO Ninja to easily interact with the server, and if you're using JavaScript, this is probably your best bet. Just plug in the Dojo URL, generate a private key, and you're off to the races!

Current Server's Dojo URL and Config

Beep boop, my Dojo URL is: https://dojo.babbage.systems

I am currently configured to allow Paymail registration under the following internet domain names:

Primary Paymail Domain (4 the n00bs)

By default, when n00bs create Paymail accounts by using a new key for the first time, I am configured to give them a random handle @gateway.cash.

I Offer Custom Paymail Hosting!

If you want, you can point your own custom domain's DNS records at me, and for a low monthly fee (currently $10 USD), you can have a customized Paymail handle like checkout@mycoolstore.com. If you are interested, you should contact my administrator. He is Ty Everett, and you can find him on Slack.

API Request Authentication

To manage coins and Paymail handles, you will verify yourself by signing all your requests with a root extended private key (xpriv key for short).

I will route your coins to some derived child keys of your xpriv, which you can customize in your Receive Policy. Check out Bitcoin Improvement Proposal #32 for more info on child keys and derivation.

A new user is created the first time a properly-signed request comes in from a new root xpriv key. A random Paymail handle is automatically generated, and it can be changed later.

I never need to see your xpriv key itself, I only check that the signatures you make are valid. This way, you get to keep custody over all your coins. I will lock up your new, incoming coins with the key that only you have, and give you signing instructions whenever you want to spend.

Authentication Object

To authenticate requests, provide an auth object in the POST request body. All authenticated requests are POST requests. It must contain the following fields:

The order of the fields when creating the signature (body, dt, url, xpub) is important! The complete URL (not just the relative path) should be used. The dt must be within 2 minutes of the server clock. Sign data in the following format with the root xpriv key:

{"body":{"bar":"baz"},"dt":1606590241,"url":"https://dojo.babbage.systems/foo","xpub":"xpub661MyMwAq..."}

If you run into any problems, you should check out how the UTXO Ninja library signs its requests, and model your implementation from that.

Receive Policies

Your Receive Policy is how you will define the types, amounts and BIP32 derivation paths for incoming coins destined for your Paymail handle(s). Receive Policies have the below fields:

You should be aware that the policies surrounding the minimum desired value of UTXOs will take precedence over the policies surrounding the number of UTXOs to be kept on hand. If this bugs you, please yell at us.

Getting Started

Generally, the first request you will want to make after you generate a key is "getCurrentReceivePolicy". Then, you can use "setReceivePolicy" if necessary to update it. Use "getCurrentPaymails" to learn what your Paymail handle is, then use the "createTransaction" flow to fund your account with some inputs. Once you've got some coins under your new key, you can use "changePaymail" to claim the handle of your choice.

Just generate a fresh xpriv key, then sign and send your first request! Your account will be created automatically.

The Dojo API Docs

post /getCurrentReceivePolicy

Use this endpoint to obtain the current receive policy for your xpub key. See the section on receive policies for information about how to create the best receive policy for your application's needs.

Parameters

Example Response

{
  "policy": {
    "...": "..."
  }
}

post /setReceivePolicy

Use this endpoint to update the receive policy associated with your xpub key. Refer to the receive policy section for more information on the required fields in the policy object.

Parameters

Example Response

{
  "status": "success"
}

post /getCurrentPaymails

Use this endpoint to obtain a list of the Paymails associated with your xpub key. In the current version of this API, only one Paymail is supported per user. In subsequent versions, we may add support for multiple aliases, depending on user and developer feedback.

Parameters

Example Response

{
  "aliases": [
    "who@john.galt"
  ]
}

post /changePaymail

Use this endpoint to change your Paymail handle. Currently, you need to have at least one unspent output registered with the Dojo in order to change your Paymail.

Parameters

Example Response

{
  "newPaymail": "joe@example.com"
}

post /createTransaction

This endpoint creates a new transaction, supplying you with additional inputs to fund it and/or providing change outputs as necessary. You can specify inputs and outputs, provide a fee model to use, and pick which types of Dojo-managed UTXOs you want to spend (if any). After you create and sign the transaction, you MUST immediately use "processTransaction" to activate any new outputs, or "updateTransactionStatus" to cancel it and free up any selected inputs. Note that any selected inputs will not be usable in any other transactions, unless you cancel this transaction without sending it. This is to prevent accidental double-spending of inputs where a second transaction would have selected overlapping inputs as the earlier one before the earlier one has a chance to be processed.

Parameters

Example Response

{
  "referenceNumber": "xxx",
  "inputs": {
    "txid1...": {
      "providedBy": "you",
      "outputsToRedeem": [
        1
      ],
      "rawTx": "01000000...",
      "...": "other envelope fields (proof or inputs/mapiResponses)"
    },
    "txid2...": {
      "providedBy": "you",
      "outputsToRedeem": [
        2,
        4
      ],
      "rawTx": "01000000...",
      "...": "other envelope fields (proof or inputs/mapiResponses)"
    },
    "txid3...": {
      "providedBy": "dojo",
      "outputsToRedeem": [
        3,
        6
      ],
      "instructions": {
        "3": {
          "type": "P2RPH",
          "derivationPath": "m/3/24"
        },
        "6": {
          "type": "P2PKH",
          "derivationPath": "m/2/14"
        }
      },
      "rawTx": "01000000...",
      "...": "other envelope fields (proof or inputs/mapiResponses)"
    },
    "txid4...": {
      "providedBy": "you-and-dojo",
      "outputsToRedeem": [
        0,
        1
      ],
      "instructions": {
        "1": {
          "type": "P2RPH",
          "derivationPath": "m/3/18"
        }
      },
      "rawTx": "01000000...",
      "...": "other envelope fields (proof or inputs/mapiResponses)"
    }
  },
  "outputs": [
    {
      "providedBy": "you",
      "script": "...442266889955",
      "satoshis": 1337
    },
    {
      "providedBy": "you",
      "script": "...888844446666",
      "satoshis": 1033
    },
    {
      "providedBy": "dojo",
      "purpose": "change",
      "destinationBasket": "loose-poket-change",
      "script": "...88ac88ac88ac",
      "satoshis": 4488
    },
    {
      "providedBy": "dojo",
      "purpose": "service-charge",
      "script": "...a8cca8cc8caa",
      "satoshis": 10
    }
  ]
}

post /processTransaction

After creating a transaction with createTransaction and signing it, submit the reference number and the payment envelope containing the transaction to this endpoint, thereby marking the change outputs as spendable and confirming that the selected inputs have been spent.

Parameters

Example Response

{
  "note": "The transaction has been processed and broadcast.",
  "mapiResponses": [
    {
      "payload": "{\"apiVersion\":\"1.3.0\",\"timestamp\":\"2021-07-22T06:10:16.8249798Z\",\"txid\":\"72fb10d4189f51d404e7098cfa63bda24ca403221f610b096bb15f5ed2f3f07a\",\"returnResult\":\"success\",\"resultDescription\":\"\",\"minerId\":\"030d1fe5c1b560efe196ba40540ce9017c20daa9504c4c4cec6184fc702d9f274e\",\"currentHighestBlockHash\":\"000000000000000009633c9e88483812c4a39a41e1eb95cdb18cce213196d202\",\"currentHighestBlockHeight\":696983,\"txSecondMempoolExpiry\":0}",
      "signature": "304402205bd36673a85c4843df0c3f34cc65a8de446bed884a98a91df8a6d1b7f828b8d7022076c954e93b21b30945d7382c54f26a238db216e5ad438601fabe69e2bc5bf701",
      "publicKey": "030d1fe5c1b560efe196ba40540ce9017c20daa9504c4c4cec6184fc702d9f274e",
      "encoding": "UTF-8",
      "mimetype": "application/json"
    }
  ]
}

post /getTransactions

Use this endpoint to obtain a list of transactions associated with your xpub key.

Parameters

Example Response

{
  "totalTransactions": 2,
  "transactions": [
    {
      "txid": "txid1",
      "status": "completed",
      "amount": 314159,
      "senderPaymail": "foo@bar.com",
      "recipientPaymail": "me@example.com",
      "note": "Here is money.",
      "isOutgoing": true,
      "created_at": "2020-11-28T18:25:26.104Z",
      "referenceNumber": "ref_no",
      "labels": [
        "Label #1",
        "Label #2"
      ]
    },
    {
      "txid": "txid2",
      "status": "completed",
      "amount": 123456,
      "senderPaymail": "foo@bar.com",
      "recipientPaymail": "ben@dover.com",
      "note": "Here is more money.",
      "isOutgoing": true,
      "created_at": "2020-12-28T14:15:16.458Z",
      "referenceNumber": "ref_no",
      "labels": [
        "Label #1",
        "Label #3",
        "Label #4"
      ]
    }
  ]
}

post /getPendingTransactions

Use this endpoint to get a list of the transactions that need to be either signed and submitted, or canceled.

Parameters

Example Response

[
  {
    "amount": 314159,
    "senderPaymail": "foo@bar.com",
    "created_at": "2020-11-28T18:25:26.104Z",
    "referenceNumber": "ref_no"
  },
  {
    "amount": 123456,
    "senderPaymail": "foo@bar.com",
    "created_at": "2020-12-28T14:15:16.458Z",
    "referenceNumber": "ref_no"
  }
]

post /getTotalOfUnspentOutputs

Use this endpoint to obtain the total value of the unspent transaction outputs. Currently, the total value is always returned, but in the future, if we decide to implement output baskets, transaction labels and other sorting schemes, it will be possible to provide more specificity.

Parameters

Example Response

{
  "total": 45568
}

post /setNameAndPhotoURL

Use this endpoint to set a name and profile photo URL that will be resolved when people request an avatar for the Paymail handle.

Parameters

Example Response

{
  "status": "success"
}

post /getTransactionOutputs

Use this endpoint to obtain a list of transaction outputs managed by this server.

Parameters

Example Response

[
  {
    "txid": "123...",
    "vout": 5,
    "amount": 314159,
    "outputScript": "76...",
    "type": "P2PKH",
    "spendable": true
  }
]

post /getTotalOfAmounts

Use this endpoint to find the aggregate total of the amounts of all transactions of a given direction, in a given date range, or with a specific label.

Parameters

Example Response

{
  "total": 198254
}

post /updateTransactionStatus

Use this endpoint to update the status of a transaction. This is useful for flagging incomplete transactions as aborted or reverting a completed transaction back into a pending status if it never got confirmed. Setting the status to "waitingForSenderToSend" or "completed" will make any selected UTXOs non-spendable elsewhere, while any other status value will free up the UTXOs for use in other transactions.

Parameters

Example Response

{
  "status": "success"
}

post /updateOutpointStatus

Use this endpoint to update the status of one of your outputs, given as the TXID of a transaction and the vout (output index) in that transaction. This is useful for flagging transaction outpoints as spent if they were inadvertantly broadcasted or used without properly submitting them to the Dojo, or to undo the spending of an output if it was never actually spent.

Parameters

Example Response

{
  "status": "success"
}

post /labelTransaction

Use this endpoint to add a label to an existing transaction.

Parameters

Example Response

{
  "status": "success"
}

post /unlabelTransaction

Use this endpoint to remove a label to a transaction.

Parameters

Example Response

{
  "status": "success"
}

post /requestOutputsForP2PTransaction/:paymail

Use this endpoint to request outputs that a Paymail user will accept for payment. Provide the number of satoshis you want to request, then use the specified outputs in a BSV transaction that you will submit along with the reference number to the submitP2PTransaction endpoint for validation and broadcast.

Parameters

Example Response

{
  "outputs": [
    {
      "script": "76a914f32281faa74e2ac037493f7a3cd317e8f5e9673688ac",
      "satoshis": 10000
    },
    {
      "script": "76a914f32281faa74e2a455555567a3cd317e8f5e9673688ac",
      "satoshis": 45557
    }
  ],
  "reference": "fasodjfadsfasdfas="
}

post /submitSPVTransaction/:paymail

After requesting payment outputs with the requestOutputsForP2PTransaction function, use this endpoint to provide an SPV envelope with a signed transaction that contains the specified outputs. Also include the reference number you received with the output scripts and amounts. This endpoint will broadcast the transaction to the Bitcoin network.

Parameters

Example Response

{
  "txid": "123...",
  "note": "The transaction has been received."
}

get /getAvatarForPaymail/:paymail

Use this endpoint to obtain the avatar (name and profile photo URL) for a given Paymail alias which is hosted on this server. The photo URL may be an HTTP or UHRP-compliant URL.

Parameters

Example Response

{
  "name": "John Smith",
  "photoURL": "https://foo.com/photo.png"
}

get /verifyPublicKeyForPaymail/:paymail/:pubkey

Use this endpoint to verify that a given Paymail identity public key is owned by a Paymail handle being hosted by this server.

Parameters

Example Response

{
  "handle": "foo@bar.com",
  "pubkey": "032fc032bd3465c3870c8bd0582b934ff3803e176819c7f80693dcfafdf83b539c"
}

get /getIdentityKeyForPaymail/:paymail

Use this endpoint to obtain the identity key associated with a Paymail that is hosted on this server.

Parameters

Example Response

{
  "bsvalias": "1.0",
  "handle": "john@doe.com",
  "pubkey": "032fc032bd3465c3870c8bd0582b934ff3803e176819c7f80693dcfafdf83b539c"
}

post /deprecatedSubmitP2PTransaction/:paymail

This is DEPRECATED, you should use submitSPVTransaction instead. After requesting payment outputs with the requestOutputsForP2PTransaction function, use this endpoint to submit the signed transaction hex for a transaction that contains the specified outputs. Also include the reference number you received with the output scripts and amounts. This endpoint will broadcast the transaction to the Bitcoin network.

Parameters

Example Response

{
  "txid": "123...",
  "mapiResponses": [
    {
      "...": "Affirmative mAPI broadcast or status response"
    }
  ],
  "note": "The transaction has been received."
}

post /mapiCallback

This endpoint is for the internal use of the server, to process mAPI response callbacks after transactions are broadcast.

Parameters

Example Response

{
  "status": "success"
}

post /migrate

This is an administrative endpoint used by the server administrator to run any new database migrations and bring the database schema up-to-date.

Parameters

Example Response

{
  "status": "success"
}

API Errors

Errors are sent back with appropriate HTTP status codes. The status field of the response object will be "error" in these cases. The object will also contain a machine-readable code field and a human-readable description field. See the Table of Errors for a complete list of error codes.

Table of Errors

Notes on ERR_NOT_SUFFICIENT_FUNDS

When you use the createTransaction endpoint to attempt to request inputs and change outputs to a transaction that would require more funds than are available in the current context (you are trying to spend more Bitcoins than you have on hand), the server will generate ERR_NOT_SUFFICIENT_FUNDS.

In addition to the error code and a human-readable description field, the error object will also contain totalSatoshisNeeded and moreSatoshisNeeded fields. These values are calculated based on the cost of only the required outputs and whatever inputs were available to be selected. They do not necessarily reflect the actual amount of satoshis you need to have on hand, because we do not account for the cost of miner fees associated with redeeming and spending the new output(s) in the transaction.

Depending on the application, it can be better to over-shoot these estimates by a little and have change outputs. Factor in your current receive policy, fee rates, the types of outputs used and others if you need to be precise.

Tips and Tricks

As you build, you may find the tips and tricks from this section useful when architecting the best applications and services.

Dealing With "Phantom UTXOs"

Sometimes, Dojo-managed UTXOs get inadvertently spent without properly going through the transaction creation or processing steps. There are two ways to deal with this type of situation, depending on the circumstances.

1. Just use processTransaction: works when createTransaction was used

If, for example, you created a transaction with createTransaction, sent it to a merchant who broadcasted it and accepted it as payment, but before you could use processTransaction to mark your UTXOs as spent and activate your change outputs, your internet connection dropped, then the Dojo does not know that the transaction was ever broadcast.

It may try to spend the same UTXOs again (though this is unlikely in recent versions), causing for future transactions to be rejected with missing inputs. To resolve this, when you come back online (or when you otherwise learn of the error), you could find the reference number for the missing transaction with getTransactions, then use a service provider to obtain the payment envelope and subsequently process it as normal. The next section describes a more universal (though somewhat less convenient) method, useful in more extreme cases.

2. Manually mark UTXOs as spent: works no matter what

If, for example, you loaded your Dojo XPRIV key into other software and sent transactions using the traditional non-P2P way (do not do this!), the transactions were not created in accordance with Dojo's instructions, and createTransaction was never even used. Dojo does not know about them, because Dojo never scans the blockchain for transactions. You don't have a reference number, so you can't just process them with processTransaction.

You can recover from this by using the updateOutpointStatus endpoint, manually flagging the afflicted UTXOs as spent. That way, Dojo won't try to spend them again. If you are in a situation where you now have rogue change outputs created by other software, if you want to bring them back under Dojo management here is how:

Just use createTransaction while specifying all of the rogue change UTXOs as inputs. Specify no outputs, thereby sending all of the inputs back under Dojo management. Sign the transaction and process it as normal with processTransaction and your reference number to get your UTXOs back into the system.

Warnings & Cautions

Dojo never holds your private keys, but there are still risks if you use it carelessly. Always be mindful of what you are signing!

Be Careful with P2RPH!

Be extremely careful with P2RPH transactions. Only use the K-chain value once for the signature. Never sign different messages with the same K-chain value and private key, otherwise the K-value and private key could be calculated. P2RPH is disabled by default, you enable and use it at your own risk.

How I Make Money

Every once in a while, a "service charge" output will be added when you use "createTransaction". These will be really small, and this is disabled for now. Everything except Paymail hosting on your custom domain is currently free.

You are welcome, enjoy your weekend.

Also, ©, ®, ™ and stuff. Especially ™ — I was Dojo first! (while you were still YourCoins)