---
# System prepended metadata

title: brainstorming tbdex rest api

---


# Each db table will have these columns:
- created datetime
- updated datetime
- threadid
- parentid
- id
- signature

# GET /offerings
tbDEX offering response to Alice
```javascript
{
  id                    : 'tbdex:offering:123',
  description           : 'BTC -> KES offramp by YC',
  // GET /rates rate.buy, conver USD-KES from rate.buy to BTC-KES (maths)
  quoteUnitsPerBaseUnit : '0.00000024',
  baseCurrency          : {
    currencyCode : 'KES',
    minSubunits  : '1', // GET /channels use channel.min
    maxSubunits  : '100000000' // GET /channels use channel.max
  },
  quoteCurrency: {
    currencyCode : 'BTC',
    minSubunits  : '1000',
    maxSubunits  : '10000'
  },
  credentialRequirements: 'ey...', // JWS of... PD with proof object?
  payinMethods: [{
    kind        : 'BTC_CUSTODIAL_BALANCE',
  }],
  // this implies YC PFI would store the associated channelId and networkId per each payment method 
  // and do a lookup when it receives an RFQ
  payoutMethods: [{
    // i.e. 'BANKACCOUNT_DIAMONDBANK'
    // flattened CHANNELNAME_NETWORKNAME that is a valid combination
    kind                   : 'MOMO_MPESA', 
	// TODO: add this to tbdex offering type?
    description            : 'Get mobile money payout via MPESA telco',
    // GET /channels channel.feeUSD convert to cents
    feeSubunits            : '10', 
    requiredPaymentDetails : 
        {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "title": "Mobile Money withdrawal via MPESA required info",
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "recipientName": {
              "description": "Recipient Full Name",
              "type": "string"
            },
            "recipientAccountNumber": {
              "description": "Recipient Phone Number",
              "type": "string"
            },
            "senderName": {
              "description": "Sender Full Name",
              "type": "string"
            }
          }
        }
    }],
  createdTime: '2023-06-27T12:34:56Z'
  // TODO: do we want to add updatedTime field in tbDEX offering type?
}
```
^ converted to db tables:
## Offerings
- id
- credentialRequirements
- baseCurrencyCode
- baseCurrencyMinSubunits
- baseCurrencyMaxSubunits
- quoteCurrencyCode
- quoteCurrencyMinSubunits
- quoteCurrencyMaxSubunits

## PayoutMethods
- kind
- channelId
- networkId
- fee
- offeringId (FK from `Offerings.id`)

# POST /rfqs
tbDEX rfq request from Alice
```javascript
{
  ...metadata,
  id   : 'tbdex:rfq:456',
  type : 'rfq',
  body : {
    offeringId          : 'tbdex:offering:123',
    quoteAmountSubunits : '1000',
	credentials         : { ... },
    payinMethod         : {
      kind: 'BTC_BALANCE'
    },
    payoutMethod: {
      kind           : 'MOMO_MPESA',
      paymentDetails : {
        'accountName': 'James Falola',
        'accountNumber': '1111111111',
      }
    }
  }
}
```

alternatively, use hash and sign over the hash, have pii in a separate object (don't sign over the actual pii object) - provides a way for us to return GET /threads with valid signature that can be verified when we regurgitate it back to us
```javascript
{
  ...metadata,
  id   : 'tbdex:rfq:456',
  type : 'rfq',
  body : {
    offeringId          : 'tbdex:offering:123',
    quoteAmountSubunits : '1000',
	credentialHash      : '...',
    payinMethod         : {
      kind: 'BTC_BALANCE'
    },
    payoutMethod: {
      kind           : 'MOMO_MPESA',
      // todo: change to hash value? 
      paymentDetailsHash : '...'
    },
	actualPii: {
		credentials: { ... }, // needed if VC ends up including PII
		payoutMethodPaymentDetails: {
			'accountName': 'James Falola',
        	'accountNumber': '1111111111',
		}
	}
  }
}
```
^ converted to db table
## RFQs
*: think about DSL considerations, DSL3+4 fields
- offeringId
- quoteAmountSubunits
- credentials*
- piiHash
- payinMethodJsonBlob
- payoutMethodJsonBlob*

or like this:
- offeringId
- quoteAmountSubunits
- credentialHash
- payinMethodJsonBlob
- payoutMethodJsonBlob
- actualPiiCredential*
- actualPiiPayoutMethodpaymentDetails*

# GET /thread/:threadId/quote
tbDEX quote response to Alice

```javascript
{
  ...metadata,
  id   : 'tbdex:quote:543',
  type : 'quote',
  body : {
    expiryTime : "2023-08-05T02:15:06.462Z",
    base       : {
      currencyCode   : 'KES',
      amountSubunits : '33333'
    },
    quote: {
      currencyCode   : 'BTC',
      amountSubunits : '1000',
      feeSubunits    : '100'
    }
  }
}
```
^ converted to db table
## Quote
- paymentId (from YC POST /payments response body.id)
- expirationTime (from YC POST /payments response body.expiresAt)
- rfqId (isn't this already exposed in parentId?)
- baseCurrencyCode
- baseAmountSubunits
- baseFeeSubunits
- quoteCurrencyCode
- quoteAmountSubunits
- quoteFeeSubunits


# POST /thread/:threadId/order
tbDEX order request from Alice
```javascript
{
  ...metadata,
  id: 'tbdex:order:678',
  type: 'order',
  body: {
	quote_id: 'tbdex:quote:456'
  }
}
```
^ converted to db table
## Order
- quoteId (isn't this already exposed in parentId?)
- status (initially null, updated after we call POST /payments/:paymentId/accept, and also webhooks)

## OrderStatus (may not need this?)
- orderId (FK from Order.id)
- status (initially null, updated after we call POST /payments/:paymentId/accept, and also webhooks)

# GET /thread/:threadId/orderstatus
tbDEX order status
```javascript
{
  ...metadata,
  id: 'tbdex:orderstatus:566',
  type: 'orderstatus',
  body: {
	order_id: 'tbdex:order:643',
	status: 'pending'
  }
}
```