---
# System prepended metadata

title: tbDiligence API spec

---


# tbDiligence API Spec

## Auth
- HTTP Header in each request sent to tbDiligence will have `Authentication: Bearer {token}` which has
- 1. token.decoded().header contains kid == DIDPay's DID and DID#verificationMethodId
- 2. token.decoded().payload contains timestamp signed by DIDPay's private key
- use the above to verify that the request came from DIDPay


## Submit Sanction
## endpoint: `POST /submissions`
Submit user info and ask for a VC

### req body
```javascript=
{
	externalId: '${didpayAccountId}',
	subject: {
		firstName: 'alice',
		lastName: 'jones',
		dateOfBirth: '01/01/1970',
		countryOfResidency: 'US'
		countryOfCitizenship: null
	},
	automaticRescreen: true // or just rescreen everyone for pigeon
}
```

### res body
202 accepted, no response body


For subsequent calls to get VC, the caller passes in the external id that they supplied in the initial request

### tbdiligence
inserts a doodad row containing external id, doodad data, caller DID, sanctions status, last screened at, initial screen time, ...any other data needed to deterministically reproduce VC, lists screened against

VC gets created fresh every time, but is deterministic based on inputs so the internals of the objects will be the same every time you generate it

## Get Submission Result
### endpoint: `GET /submissions/:externalId`

use DID authn to check that the caller matches the DID who initially made the submission
### req body
path param: The external ID provided in the POST

### res body
- latestSanctionStatus is sanction status that's mutable over time
- returning the most recent state - we can compose the most recent state in the response, can store state changes as append only in db or mutate the state column

```javascript=
// alice was always a terrorist
{
	latestSanctionStatus: 'SANCTIONED'
	lastScreenDate: ...
	vc: null
}
	
// alice was good but _became_ a terrorist
{
	latestSanctionStatus: 'REVOKED'
	lastScreenDate: ...
	vc: {...} // issued once, later revoked vc
}
	
// alice was always a good boi
{
	latestSanctionStatus: 'NOT_SANCTIONED'
	lastScreenDate: ...
	vc: {
	  "@context": [...],
	  "id": "$uuid", // newly generated each time
	  "type": ["VerifiableCredential", "SanctionsCredential"],
	  "issuer": "...",
	  ...
	  "credentialSubject": {
	    "id": "${didpay DID}",
	    ...
	  },
	  "proof": {...} // proof that tbDiligence issued this VC
	}
}
```


### More about VC, VP, and PS...
```javascript=
// what DIDPay sends to YC PFI in RFQ.vcs
// VerifiablePresentation = PresentationSubmission + VerifiableCredential
const vpFromDidpay = {
  "@context": [...],
  ...
  "type": ["VerifiablePresentation", "CredentialManagerPresentation"],
  "verifiableCredential": [vcFromTbdiligence], // see above
  "proof": [{...}] // proof that DIDPay holds this VC
}
```
- tbDEX should support either JWS or Embedded Proof format VC
- TODO: :question: check if pex method in Sphereon accepts this ^ JSON format and string

---


## DIDPay/tbdiligence interactions
```mermaid
sequenceDiagram
autonumber

participant D as DIDPay
participant T as tbdiligence

D->>T: POST /submissions/
T->>D: 202 Accepted
D->>T: GET /submission/:externalId
T->>D: Submission (state + vc)
```

---
# tbdiligence data modeling
## ${table name}
- externalId (alice's accountId in DIDPay)
- didpay's did*
- fname*!
- lname*!
- dob!
- residence*
- citizenship
- lastSanctionStatus*
- lastScreened*
- automaticRescreen
- Credential ID - randomly generated uuid
*: fields needed to build VC. also need vendor, lists, fuzzy logic param.
!: requires thoughts on encryption - DSL 3
	- use tink for field level encryption and store key in kms
	- todo: follow up with abrook






