> For the complete documentation index, see [llms.txt](https://docs.zetrix.com/en/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zetrix.com/en/developer-resources/blockchain-as-a-services-baas/tradetrust-api/trade-trust-e-bl.md).

# Trade Trust E BL

Mint, verify, and move a transferable record (eBL) through core-engine.

## Complete and mint an eBL

> Hand back the signed record and get the mint transaction — still unsent; see this class's javadoc.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblCompleteMintReqDto":{"type":"object","description":"Request for <code>POST /tradetrust/ebl/complete-mint</code> — hand back the signed record and get the\n mint transaction. <code>beneficiary</code> and <code>holder</code> default to <code>from</code> server-side.","properties":{"preparationId":{"type":"string","minLength":1},"signedVerifiableCredential":{"type":"object","additionalProperties":{},"minProperties":1},"from":{"type":"string","description":"Must hold <code>MINTER_ROLE</code> on the registry.","minLength":1},"beneficiary":{"type":"string"},"holder":{"type":"string"}},"required":["from","preparationId","signedVerifiableCredential"]},"ResponseWrapperEblCompleteMintRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/EblCompleteMintRespDto"}}},"EblCompleteMintRespDto":{"type":"object","description":"Response of <code>POST /tradetrust/ebl/complete-mint</code> (and <code>/mint</code>, which ends at the same\n step) — the assembled record, its assigned token id, and the still-unsent mint transaction.","properties":{"verifiableCredential":{"type":"object","additionalProperties":{}},"tokenId":{"type":"string","description":"0x-prefixed 32-byte hex token id, assigned during signing rather than at prepare time."},"unsignedMintTx":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/complete-mint":{"post":{"tags":["TradeTrust eBL"],"summary":"Complete and mint an eBL","description":"Hand back the signed record and get the mint transaction — still unsent; see this class's javadoc.","operationId":"completeMint","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblCompleteMintReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperEblCompleteMintRespDto"}}}}}}}}}
```

## Mint an eBL in one call

> Mint a transferable record in one call: \<code>prepare-mint\</code> -\&gt; core-engine signs -\&gt;\
> &#x20;\<code>complete-mint\</code>. One step still to do: sign and broadcast the returned\
> &#x20;\<code>unsignedMintTx\</code>. Sends the issuer's private key to core-engine — see\
> &#x20;{@link com.myeg.z2.tradetrust.dto.req.MultikeyDto com.myeg.z2.tradetrust.dto.req.MultikeyDto}.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblMintReqDto":{"type":"object","description":"Request for <code>POST /tradetrust/ebl/mint</code> — the same build as {@link EblPrepareMintReqDto EblPrepareMintReqDto},\n plus the issuer's key pair for delegated signing and the minting address. One call, but\n <code>from</code> must still sign and broadcast the returned <code>unsignedMintTx</code> — the token does\n not exist until that is mined.\n\n <p><b>This sends the issuer's private key to core-engine.</b> See {@link MultikeyDto MultikeyDto}.","properties":{"issuerDid":{"type":"string","minLength":1},"credentialSubject":{"type":"object","additionalProperties":{},"minProperties":1},"tokenRegistry":{"type":"string","minLength":1},"chainId":{"type":"integer","format":"int64"},"chain":{"type":"string"},"context":{"type":"array","items":{"type":"string"}},"expirationDate":{"type":"string"},"renderMethod":{"type":"object","additionalProperties":{}},"qrCode":{"type":"object","additionalProperties":{}},"from":{"type":"string","description":"Must hold <code>MINTER_ROLE</code> on the registry.","minLength":1},"beneficiary":{"type":"string","description":"Initial owner of title to the goods (Title Escrow beneficiary). Defaults to <code>from</code>."},"holder":{"type":"string","description":"Initial holder / possessor. Defaults to <code>from</code>."},"keyPair":{"$ref":"#/components/schemas/MultikeyDto"}},"required":["credentialSubject","from","issuerDid","keyPair","tokenRegistry"]},"MultikeyDto":{"type":"object","description":"The issuer's Multikey key pair, <b>including its secret</b> — the payload for delegated signing\n (BT-2620: <code>POST /credentials/sign</code> via the SDK's <code>signRemote</code>/<code>issueRemote</code>).\n\n <p>All six fields are required; core-engine's schema rejects a partially built key with a 400\n rather than a partial success, so this DTO enforces the same shape locally via <code>@NotBlank</code>.\n\n <p><b>Carries a private key</b>, exactly like <code>SignBlobReqDto</code>: never logged, never\n persisted, and masked in {@link com.myeg.z2.tradetrust.dto.req.MultikeyDto#toString #toString()} so it cannot leak through request logging, an\n exception message, or a debugger. Every endpoint that accepts this DTO must be POST — a key in a\n query string ends up in access logs.","properties":{"id":{"type":"string","minLength":1},"type":{"type":"string","minLength":1},"controller":{"type":"string","description":"Must equal the <code>issuerDid</code> the preparation was created for.","minLength":1},"publicKeyMultibase":{"type":"string","minLength":1},"secretKeyMultibase":{"type":"string","minLength":1},"@context":{"type":"string","minLength":1}},"required":["@context","controller","id","publicKeyMultibase","secretKeyMultibase","type"]},"ResponseWrapperEblCompleteMintRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/EblCompleteMintRespDto"}}},"EblCompleteMintRespDto":{"type":"object","description":"Response of <code>POST /tradetrust/ebl/complete-mint</code> (and <code>/mint</code>, which ends at the same\n step) — the assembled record, its assigned token id, and the still-unsent mint transaction.","properties":{"verifiableCredential":{"type":"object","additionalProperties":{}},"tokenId":{"type":"string","description":"0x-prefixed 32-byte hex token id, assigned during signing rather than at prepare time."},"unsignedMintTx":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/mint":{"post":{"tags":["TradeTrust eBL"],"summary":"Mint an eBL in one call","description":"Mint a transferable record in one call: <code>prepare-mint</code> -&gt; core-engine signs -&gt;\n <code>complete-mint</code>. One step still to do: sign and broadcast the returned\n <code>unsignedMintTx</code>. Sends the issuer's private key to core-engine — see\n {@link com.myeg.z2.tradetrust.dto.req.MultikeyDto com.myeg.z2.tradetrust.dto.req.MultikeyDto}.","operationId":"mint","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblMintReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperEblCompleteMintRespDto"}}}}}}}}}
```

## Deploy a Token Registry

> Deploy a brand-new Token Registry — where an eBL flow starts, since \<code>prepare-mint\</code> and\
> &#x20;\<code>mint\</code> both require a \<code>tokenRegistry\</code> and there is no default.\
> \
> &#x20;\<p>Unsigned like every other write: the paying address signs and broadcasts it, and needs gas.\
> &#x20;Afterwards read the new registry's address from \<code>/onboard-issuer/registry\</code> — it is not in\
> &#x20;the receipt's \<code>contractAddress\</code>.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"OnboardIssuerReqDto":{"type":"object","description":"Request for <code>POST /tradetrust/ebl/onboard-issuer</code> — build the transaction that deploys a\n brand-new eBL Token Registry.\n\n <p>This is where an eBL flow starts. <code>tokenRegistry</code> is required on <code>prepare-mint</code> and\n <code>mint</code> and core-engine keeps no server-wide default, so without a registry of your own there\n is nothing to mint into.\n\n <p>Like every other eBL write this returns an <strong>unsigned</strong> transaction: <code>admin</code>\n (or whoever you choose to pay) signs and broadcasts it, so that address needs gas first. Deployment\n is permissionless — the registry's admin comes from an encoded parameter rather than the sender —\n so the paying address and the admin need not be the same.\n\n <p><strong>The new registry's address is not in the transaction receipt's <code>contractAddress</code>\n field.</strong> The registry is deployed by the platform's shared deployer contract, not by this\n transaction directly, so that field is null. Once the transaction succeeds, read the address from\n <code>GET /tradetrust/ebl/onboard-issuer/registry?hash=...</code>.","properties":{"name":{"type":"string","description":"The registry's ERC-721 collection name, e.g. <code>&quot;MYEG Bill of Lading&quot;</code>.","minLength":1},"symbol":{"type":"string","description":"The registry's ERC-721 symbol, e.g. <code>&quot;MYEGBL&quot;</code>.","minLength":1},"admin":{"type":"string","description":"Becomes the new registry's admin, holding <code>DEFAULT_ADMIN_ROLE</code>, <code>MINTER_ROLE</code>,\n <code>RESTORER_ROLE</code> and <code>ACCEPTER_ROLE</code> — so this is the address that will be allowed\n to mint. Typically the issuer's own operational address.","minLength":1}},"required":["admin","name","symbol"]},"ResponseWrapperUnsignedTxRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/onboard-issuer":{"post":{"tags":["TradeTrust eBL"],"summary":"Deploy a Token Registry","description":"Deploy a brand-new Token Registry — where an eBL flow starts, since <code>prepare-mint</code> and\n <code>mint</code> both require a <code>tokenRegistry</code> and there is no default.\n\n <p>Unsigned like every other write: the paying address signs and broadcasts it, and needs gas.\n Afterwards read the new registry's address from <code>/onboard-issuer/registry</code> — it is not in\n the receipt's <code>contractAddress</code>.","operationId":"onboardIssuer","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardIssuerReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperUnsignedTxRespDto"}}}}}}}}}
```

## Get the deployed registry address

> The address of the registry an \<code>onboard-issuer\</code> transaction deployed, decoded from the\
> &#x20;receipt's \<code>Deployment\</code> event. Poll while \<code>PENDING\</code>, exactly as with\
> &#x20;\<code>/tx/status\</code>.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ResponseWrapperRegistryAddressRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/RegistryAddressRespDto"}}},"RegistryAddressRespDto":{"type":"object","description":"Response of <code>GET /tradetrust/ebl/onboard-issuer/registry</code> — the address of the Token Registry\n an <code>onboard-issuer</code> transaction deployed.\n\n <p>This endpoint exists because the address is not where callers look for it. The registry is\n deployed by the platform's shared deployer contract rather than by the submitted transaction\n itself, so the receipt's <code>contractAddress</code> is null and <code>GET /tx/status</code> — which returns\n no logs — cannot show it either. The address is only in the deployer's <code>Deployment</code> event, so\n this reads the receipt and decodes it.\n\n <p>Poll while <code>status</code> is <code>PENDING</code>, exactly as with <code>/tx/status</code>: a hash the node\n has not seen yet is pending rather than absent, because over JSON-RPC \"still in the mempool\" and\n \"never existed\" are indistinguishable. <code>registry</code> is populated only on <code>SUCCESS</code>.","properties":{"transactionHash":{"type":"string"},"status":{"type":"string","enum":["SUCCESS","FAILED","PENDING"]},"registry":{"type":"string","description":"The new registry's address — the value to pass as <code>tokenRegistry</code> from here on.\n\n <p><code>null</code> while <code>PENDING</code> or on <code>FAILED</code>. Also null in one case worth\n handling: a <code>SUCCESS</code> whose logs carry no <code>Deployment</code> event, which means the hash\n belongs to some other transaction rather than an <code>onboard-issuer</code> one."}}}}},"paths":{"/tradetrust/ebl/onboard-issuer/registry":{"get":{"tags":["TradeTrust eBL"],"summary":"Get the deployed registry address","description":"The address of the registry an <code>onboard-issuer</code> transaction deployed, decoded from the\n receipt's <code>Deployment</code> event. Poll while <code>PENDING</code>, exactly as with\n <code>/tx/status</code>.","operationId":"registryAddress","parameters":[{"name":"hash","in":"query","required":true,"schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperRegistryAddressRespDto"}}}}}}}}}
```

## Prepare an eBL for signing

> Build the unsigned transferable record and its signing spec. The caller signs, then calls \<code>complete-mint\</code>.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblPrepareMintReqDto":{"type":"object","description":"Request for <code>POST /tradetrust/ebl/prepare-mint</code> — build the unsigned transferable record\n and its signing spec. <code>issuerDid</code>, <code>credentialSubject</code> and <code>tokenRegistry</code> are\n required; core-engine removed its server-wide default registry (a <code>tokenId</code> is only unique\n within one registry contract).","properties":{"issuerDid":{"type":"string","minLength":1},"credentialSubject":{"type":"object","additionalProperties":{},"minProperties":1},"tokenRegistry":{"type":"string","minLength":1},"chainId":{"type":"integer","format":"int64"},"chain":{"type":"string"},"context":{"type":"array","items":{"type":"string"}},"expirationDate":{"type":"string"},"renderMethod":{"type":"object","additionalProperties":{}},"qrCode":{"type":"object","additionalProperties":{}}},"required":["credentialSubject","issuerDid","tokenRegistry"]},"ResponseWrapperPreparedCredentialRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/PreparedCredentialRespDto"}}},"PreparedCredentialRespDto":{"type":"object","description":"Response of <code>POST /tradetrust/credentials/prepare</code> — the unsigned document plus its\n signing spec.\n\n <p><code>preparationId</code> is single-use and expires (~15 minutes); pass it unmodified to\n <code>complete</code> or <code>issue</code> alongside the signed document.","properties":{"preparationId":{"type":"string"},"unsignedVerifiableCredential":{"type":"object","additionalProperties":{}},"signingSpec":{"$ref":"#/components/schemas/SigningSpecRespDto"}}},"SigningSpecRespDto":{"type":"object","description":"Exactly how core-engine expects a prepared document to be signed — part of\n {@link PreparedCredentialRespDto PreparedCredentialRespDto}. Pass <code>mandatoryPointers</code> to the signer verbatim; core-engine\n derives it from what it actually built, so reconstructing it silently drops fields from the base proof.","properties":{"mandatoryPointers":{"type":"array","items":{"type":"string"}},"cryptoSuite":{"type":"string"},"expectedIssuerDid":{"type":"string"}}}}},"paths":{"/tradetrust/ebl/prepare-mint":{"post":{"tags":["TradeTrust eBL"],"summary":"Prepare an eBL for signing","description":"Build the unsigned transferable record and its signing spec. The caller signs, then calls <code>complete-mint</code>.","operationId":"prepareMint","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblPrepareMintReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperPreparedCredentialRespDto"}}}}}}}}}
```

## Verify an eBL

> Document integrity \<strong>and\</strong> on-chain state. Takes no \<code>tokenRegistry\</code> —\
> &#x20;unlike every other eBL route, it reads the registry and token id from inside the submitted\
> &#x20;credential. Read \<code>valid\</code> AND \<code>trusted\</code> — never \<code>valid\</code> alone.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"VerifyCredentialReqDto":{"type":"object","description":"Request for <code>POST /tradetrust/credentials/verify</code> — check signature, issuer binding and\n (if declared) revocation. Open on core-engine's side, but this service still requires its own\n caller auth like every other route (no addition to <code>SecurityConfig.PUBLIC_PATHS</code>).\n\n <p><code>trustedIssuers</code> is optional; when supplied, the response's <code>trusted</code> field\n reports whether the credential's issuer is on it.","properties":{"verifiableCredential":{"type":"object","additionalProperties":{},"minProperties":1},"trustedIssuers":{"type":"array","items":{"type":"string"}}},"required":["verifiableCredential"]},"ResponseWrapperEblVerifyRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/EblVerifyRespDto"}}},"EblVerifyRespDto":{"type":"object","description":"Response of <code>POST /tradetrust/ebl/verify</code> — document integrity <strong>and</strong> on-chain\n state. Returned for both outcomes; a burned or never-minted record is a value\n (<code>valid: false</code>), never an error.\n\n <p><b>Read <code>valid</code> AND <code>trusted</code></b> — same rule as\n <code>VerifyCredentialRespDto</code>, and for the same reason.","properties":{"valid":{"type":"boolean"},"issuer":{"type":"string"},"trusted":{"type":"boolean"},"onChain":{"$ref":"#/components/schemas/EblOnChainRespDto"},"checks":{"type":"array","items":{"$ref":"#/components/schemas/VerifyCheckRespDto"}}}},"EblOnChainRespDto":{"type":"object","description":"The registry-side view of a transferable record, part of {@link EblVerifyRespDto EblVerifyRespDto}.\n\n <p><code>beneficiary</code> and <code>holder</code> are <code>null</code> unless the record is active.","properties":{"minted":{"type":"boolean","description":"True while the token exists (active or surrendered); false if burned or never minted."},"status":{"type":"string","enum":["ACTIVE","SURRENDERED","BURNED","NOT_MINTED","UNKNOWN"]},"registry":{"type":"string","description":"The registry the record points at — worth checking rather than trusting <code>valid</code> alone:\n core-engine reports {@link Status#NOT_MINTED Status#NOT_MINTED}, not an error, for a record pointing elsewhere."},"tokenId":{"type":"string"},"titleEscrow":{"type":"string","description":"The Title Escrow owning the token while active (the registry once surrendered)."},"beneficiary":{"type":"string"},"holder":{"type":"string"}}},"VerifyCheckRespDto":{"type":"object","description":"One step of a verification, e.g. <code>signature</code>, <code>status</code>, <code>trusted-issuer</code>.","properties":{"type":{"type":"string"},"status":{"type":"string","description":"<code>&quot;passed&quot;</code> or <code>&quot;failed&quot;</code>."},"reason":{"type":"string","description":"Why the check failed; <code>null</code> when it passed."}}}}},"paths":{"/tradetrust/ebl/verify":{"post":{"tags":["TradeTrust eBL"],"summary":"Verify an eBL","description":"Document integrity <strong>and</strong> on-chain state. Takes no <code>tokenRegistry</code> —\n unlike every other eBL route, it reads the registry and token id from inside the submitted\n credential. Read <code>valid</code> AND <code>trusted</code> — never <code>valid</code> alone.","operationId":"verify","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyCredentialReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperEblVerifyRespDto"}}}}}}}}}
```

## Accept a surrender

> The issuer finalizes a returned record; it is burned and retired.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblActionReqDto":{"type":"object","description":"The two fields every eBL write that takes no extra parameter needs: <code>surrender</code>,\n <code>accept-surrender</code>, <code>reject-surrender</code>, <code>reject-transfer-holder</code>,\n <code>reject-transfer-beneficiary</code>, <code>reject-transfer-owners</code>. Extended by the writes that\n need more — see {@link EblTransferHolderReqDto EblTransferHolderReqDto}, {@link EblNewBeneficiaryReqDto EblNewBeneficiaryReqDto},\n {@link EblTransferOwnersReqDto EblTransferOwnersReqDto}.\n\n <p><code>tokenId</code> is not here — every eBL write takes it as a path variable, not a body field.","properties":{"from":{"type":"string","minLength":1},"tokenRegistry":{"type":"string","minLength":1}},"required":["from","tokenRegistry"]},"ResponseWrapperUnsignedTxRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/{tokenId}/accept-surrender":{"post":{"tags":["TradeTrust eBL"],"summary":"Accept a surrender","description":"The issuer finalizes a returned record; it is burned and retired.","operationId":"acceptSurrender","parameters":[{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblActionReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperUnsignedTxRespDto"}}}}}}}}}
```

## Get the endorsement chain

> The record's full transfer history, oldest first.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ResponseWrapperEndorsementChainRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/EndorsementChainRespDto"}}},"EndorsementChainRespDto":{"type":"object","description":"Response of <code>GET /tradetrust/ebl/{tokenId</code>/endorsement-chain} — the record's full transfer\n history, oldest first.\n\n <p>Events stay as <code>Map&lt;String, Object&gt;</code> rather than a typed class, matching the SDK's own\n choice: core-engine adds event types and fields over time. Observed fields include <code>type</code>\n (<code>INITIAL</code>, <code>TRANSFER_BENEFICIARY</code>, <code>TRANSFER_HOLDER</code>, …), <code>owner</code>,\n <code>holder</code>, <code>transactionHash</code>, <code>transactionIndex</code>, <code>blockNumber</code>,\n <code>timestamp</code> (epoch milliseconds) and <code>remark</code>.","properties":{"tokenId":{"type":"string"},"chain":{"type":"array","items":{"type":"object","additionalProperties":{}}}}}}},"paths":{"/tradetrust/ebl/{tokenId}/endorsement-chain":{"get":{"tags":["TradeTrust eBL"],"summary":"Get the endorsement chain","description":"The record's full transfer history, oldest first.","operationId":"endorsementChain","parameters":[{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}},{"name":"tokenRegistry","in":"query","required":true,"schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperEndorsementChainRespDto"}}}}}}}}}
```

## Nominate the next beneficiary

> The beneficiary nominates who may take title next — step 1 of the two-step title transfer.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblNewBeneficiaryReqDto":{"type":"object","description":"Request body shape shared by <code>POST /tradetrust/ebl/{tokenId</code>/transfer-beneficiary}\n (irreversible once broadcast) and <code>POST /tradetrust/ebl/{tokenId</code>/nominate} (step 1 of the\n two-step title transfer) — both are exactly <code>newBeneficiary</code> + the base action fields.","properties":{"from":{"type":"string","minLength":1},"tokenRegistry":{"type":"string","minLength":1},"newBeneficiary":{"type":"string","minLength":1}},"required":["from","newBeneficiary","tokenRegistry"]},"ResponseWrapperUnsignedTxRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/{tokenId}/nominate":{"post":{"tags":["TradeTrust eBL"],"summary":"Nominate the next beneficiary","description":"The beneficiary nominates who may take title next — step 1 of the two-step title transfer.","operationId":"nominate","parameters":[{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblNewBeneficiaryReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperUnsignedTxRespDto"}}}}}}}}}
```

## Get the current owner

> The Title Escrow currently owning the token (or the registry, once surrendered).

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ResponseWrapperEblOwnerRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/EblOwnerRespDto"}}},"EblOwnerRespDto":{"type":"object","description":"Response of <code>GET /tradetrust/ebl/{tokenId</code>/owner}.","properties":{"tokenId":{"type":"string"},"owner":{"type":"string","description":"The Title Escrow address holding the token (or the registry, once surrendered)."}}}}},"paths":{"/tradetrust/ebl/{tokenId}/owner":{"get":{"tags":["TradeTrust eBL"],"summary":"Get the current owner","description":"The Title Escrow currently owning the token (or the registry, once surrendered).","operationId":"owner","parameters":[{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}},{"name":"tokenRegistry","in":"query","required":true,"schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperEblOwnerRespDto"}}}}}}}}}
```

## Reject a surrender

> The issuer returns a surrendered record to the last holder, active again.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblActionReqDto":{"type":"object","description":"The two fields every eBL write that takes no extra parameter needs: <code>surrender</code>,\n <code>accept-surrender</code>, <code>reject-surrender</code>, <code>reject-transfer-holder</code>,\n <code>reject-transfer-beneficiary</code>, <code>reject-transfer-owners</code>. Extended by the writes that\n need more — see {@link EblTransferHolderReqDto EblTransferHolderReqDto}, {@link EblNewBeneficiaryReqDto EblNewBeneficiaryReqDto},\n {@link EblTransferOwnersReqDto EblTransferOwnersReqDto}.\n\n <p><code>tokenId</code> is not here — every eBL write takes it as a path variable, not a body field.","properties":{"from":{"type":"string","minLength":1},"tokenRegistry":{"type":"string","minLength":1}},"required":["from","tokenRegistry"]},"ResponseWrapperUnsignedTxRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/{tokenId}/reject-surrender":{"post":{"tags":["TradeTrust eBL"],"summary":"Reject a surrender","description":"The issuer returns a surrendered record to the last holder, active again.","operationId":"rejectSurrender","parameters":[{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblActionReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperUnsignedTxRespDto"}}}}}}}}}
```

## Reject a beneficiary transfer

> Decline an incoming beneficiary transfer.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblActionReqDto":{"type":"object","description":"The two fields every eBL write that takes no extra parameter needs: <code>surrender</code>,\n <code>accept-surrender</code>, <code>reject-surrender</code>, <code>reject-transfer-holder</code>,\n <code>reject-transfer-beneficiary</code>, <code>reject-transfer-owners</code>. Extended by the writes that\n need more — see {@link EblTransferHolderReqDto EblTransferHolderReqDto}, {@link EblNewBeneficiaryReqDto EblNewBeneficiaryReqDto},\n {@link EblTransferOwnersReqDto EblTransferOwnersReqDto}.\n\n <p><code>tokenId</code> is not here — every eBL write takes it as a path variable, not a body field.","properties":{"from":{"type":"string","minLength":1},"tokenRegistry":{"type":"string","minLength":1}},"required":["from","tokenRegistry"]},"ResponseWrapperUnsignedTxRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/{tokenId}/reject-transfer-beneficiary":{"post":{"tags":["TradeTrust eBL"],"summary":"Reject a beneficiary transfer","description":"Decline an incoming beneficiary transfer.","operationId":"rejectTransferBeneficiary","parameters":[{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblActionReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperUnsignedTxRespDto"}}}}}}}}}
```

## Reject a holder transfer

> Decline an incoming holder transfer. Not the same as {@link com.myeg.z2.tradetrust.controller.EblController#rejectSurrender #rejectSurrender} — unrelated flows.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblActionReqDto":{"type":"object","description":"The two fields every eBL write that takes no extra parameter needs: <code>surrender</code>,\n <code>accept-surrender</code>, <code>reject-surrender</code>, <code>reject-transfer-holder</code>,\n <code>reject-transfer-beneficiary</code>, <code>reject-transfer-owners</code>. Extended by the writes that\n need more — see {@link EblTransferHolderReqDto EblTransferHolderReqDto}, {@link EblNewBeneficiaryReqDto EblNewBeneficiaryReqDto},\n {@link EblTransferOwnersReqDto EblTransferOwnersReqDto}.\n\n <p><code>tokenId</code> is not here — every eBL write takes it as a path variable, not a body field.","properties":{"from":{"type":"string","minLength":1},"tokenRegistry":{"type":"string","minLength":1}},"required":["from","tokenRegistry"]},"ResponseWrapperUnsignedTxRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/{tokenId}/reject-transfer-holder":{"post":{"tags":["TradeTrust eBL"],"summary":"Reject a holder transfer","description":"Decline an incoming holder transfer. Not the same as {@link com.myeg.z2.tradetrust.controller.EblController#rejectSurrender #rejectSurrender} — unrelated flows.","operationId":"rejectTransferHolder","parameters":[{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblActionReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperUnsignedTxRespDto"}}}}}}}}}
```

## Reject a combined transfer

> Decline an incoming combined (owners) transfer.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblActionReqDto":{"type":"object","description":"The two fields every eBL write that takes no extra parameter needs: <code>surrender</code>,\n <code>accept-surrender</code>, <code>reject-surrender</code>, <code>reject-transfer-holder</code>,\n <code>reject-transfer-beneficiary</code>, <code>reject-transfer-owners</code>. Extended by the writes that\n need more — see {@link EblTransferHolderReqDto EblTransferHolderReqDto}, {@link EblNewBeneficiaryReqDto EblNewBeneficiaryReqDto},\n {@link EblTransferOwnersReqDto EblTransferOwnersReqDto}.\n\n <p><code>tokenId</code> is not here — every eBL write takes it as a path variable, not a body field.","properties":{"from":{"type":"string","minLength":1},"tokenRegistry":{"type":"string","minLength":1}},"required":["from","tokenRegistry"]},"ResponseWrapperUnsignedTxRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/{tokenId}/reject-transfer-owners":{"post":{"tags":["TradeTrust eBL"],"summary":"Reject a combined transfer","description":"Decline an incoming combined (owners) transfer.","operationId":"rejectTransferOwners","parameters":[{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblActionReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperUnsignedTxRespDto"}}}}}}}}}
```

## Surrender an eBL

> The holder returns the record to the issuer — step 1 of 3 in the end-of-life flow.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblActionReqDto":{"type":"object","description":"The two fields every eBL write that takes no extra parameter needs: <code>surrender</code>,\n <code>accept-surrender</code>, <code>reject-surrender</code>, <code>reject-transfer-holder</code>,\n <code>reject-transfer-beneficiary</code>, <code>reject-transfer-owners</code>. Extended by the writes that\n need more — see {@link EblTransferHolderReqDto EblTransferHolderReqDto}, {@link EblNewBeneficiaryReqDto EblNewBeneficiaryReqDto},\n {@link EblTransferOwnersReqDto EblTransferOwnersReqDto}.\n\n <p><code>tokenId</code> is not here — every eBL write takes it as a path variable, not a body field.","properties":{"from":{"type":"string","minLength":1},"tokenRegistry":{"type":"string","minLength":1}},"required":["from","tokenRegistry"]},"ResponseWrapperUnsignedTxRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/{tokenId}/surrender":{"post":{"tags":["TradeTrust eBL"],"summary":"Surrender an eBL","description":"The holder returns the record to the issuer — step 1 of 3 in the end-of-life flow.","operationId":"surrender","parameters":[{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblActionReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperUnsignedTxRespDto"}}}}}}}}}
```

## Transfer the beneficiary

> Transfer title to the goods. Irreversible once the returned transaction is broadcast.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblNewBeneficiaryReqDto":{"type":"object","description":"Request body shape shared by <code>POST /tradetrust/ebl/{tokenId</code>/transfer-beneficiary}\n (irreversible once broadcast) and <code>POST /tradetrust/ebl/{tokenId</code>/nominate} (step 1 of the\n two-step title transfer) — both are exactly <code>newBeneficiary</code> + the base action fields.","properties":{"from":{"type":"string","minLength":1},"tokenRegistry":{"type":"string","minLength":1},"newBeneficiary":{"type":"string","minLength":1}},"required":["from","newBeneficiary","tokenRegistry"]},"ResponseWrapperUnsignedTxRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/{tokenId}/transfer-beneficiary":{"post":{"tags":["TradeTrust eBL"],"summary":"Transfer the beneficiary","description":"Transfer title to the goods. Irreversible once the returned transaction is broadcast.","operationId":"transferBeneficiary","parameters":[{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblNewBeneficiaryReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperUnsignedTxRespDto"}}}}}}}}}
```

## Transfer the holder

> Hand possession of the record to another party. Irreversible once the returned transaction is broadcast.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblTransferHolderReqDto":{"type":"object","description":"Request for <code>POST /tradetrust/ebl/{tokenId</code>/transfer-holder} — irreversible once broadcast.","properties":{"from":{"type":"string","minLength":1},"tokenRegistry":{"type":"string","minLength":1},"newHolder":{"type":"string","minLength":1}},"required":["from","newHolder","tokenRegistry"]},"ResponseWrapperUnsignedTxRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/{tokenId}/transfer-holder":{"post":{"tags":["TradeTrust eBL"],"summary":"Transfer the holder","description":"Hand possession of the record to another party. Irreversible once the returned transaction is broadcast.","operationId":"transferHolder","parameters":[{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblTransferHolderReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperUnsignedTxRespDto"}}}}}}}}}
```

## Transfer beneficiary and holder

> Move beneficiary and holder together, atomically, in one transaction.

```json
{"openapi":"3.1.0","info":{"title":"myeg-z2-service - TradeTrust","version":"0.0.1"},"tags":[{"name":"TradeTrust eBL","description":"Mint, verify, and move a transferable record (eBL) through core-engine."}],"servers":[{"url":"https://api-sandbox.zetrix.com/z2","description":"Testnet / UAT, through AWS API Gateway. Needs X-API-Key in addition to the bearer token."}],"security":[{"bearerAuth":[],"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"OAuth2 bearer token from the shared BaaS auth server.\n\nEvery endpoint in this subset requires one. Note the security filter runs BEFORE routing, so an unauthenticated request to a path that does not exist also answers 401, not 404 - a 404 is only visible to an authenticated caller.","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"EblTransferOwnersReqDto":{"type":"object","description":"Request for <code>POST /tradetrust/ebl/{tokenId</code>/transfer-owners} — moves beneficiary and\n holder together, atomically, in one transaction.","properties":{"from":{"type":"string","minLength":1},"tokenRegistry":{"type":"string","minLength":1},"newBeneficiary":{"type":"string","minLength":1},"newHolder":{"type":"string","minLength":1}},"required":["from","newBeneficiary","newHolder","tokenRegistry"]},"ResponseWrapperUnsignedTxRespDto":{"type":"object","description":"Standard BaaS response envelope. Mirrors the shape used across the microservices so\n callers get a consistent contract on L2 as on L1.","properties":{"success":{"type":"boolean"},"errorCode":{"type":"string"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/UnsignedTxRespDto"}}},"UnsignedTxRespDto":{"type":"object","description":"An <strong>unsigned</strong> EVM transaction, returned by every eBL write, by mint, and by\n <code>onboard-issuer</code>. Nothing has happened on-chain until the <code>from</code> address signs and\n broadcasts it.\n\n <p>Four calls on this same service finish the job:\n\n <ol>\n   <li><code>POST /tx/generate-blob</code> with <code>from</code> plus the <code>to</code>, <code>data</code> and\n       <code>value</code> below, which returns the RLP-encoded <code>blob</code>.\n   <li><code>POST /tx/sign-blob</code> with that <code>blob</code> — or sign it yourself and skip this call.\n   <li><code>POST /tx/submit</code> with the <code>signedBlob</code>.\n   <li><code>GET /tx/status?hash=...</code> until it reports <code>SUCCESS</code>.\n </ol>\n\n <p><b>Step 1 is not optional.</b> <code>/tx/sign-blob</code> takes a <code>blob</code> string, not the\n object below, so handing this response straight to it fails validation — an easy trap, and one\n this javadoc itself set until BT-2620's follow-up corrected it.\n\n <p><code>chainId</code> is informational: <code>/tx/sign-blob</code> signs with the chain this service is\n configured for, read live from the node. It matches when both this service and core-engine point\n at the same chain, which is the only supported arrangement — worth asserting rather than assuming\n if you run your own deployment of either.","properties":{"to":{"type":"string","description":"Contract to call — the token registry, or a Title Escrow."},"data":{"type":"string","description":"ABI-encoded calldata."},"value":{"type":"string","description":"Wei value as a decimal string; <code>&quot;0&quot;</code> for every eBL operation."},"chainId":{"type":"integer","format":"int64","description":"Chain the transaction must be signed for."}}}}},"paths":{"/tradetrust/ebl/{tokenId}/transfer-owners":{"post":{"tags":["TradeTrust eBL"],"summary":"Transfer beneficiary and holder","description":"Move beneficiary and holder together, atomically, in one transaction.","operationId":"transferOwners","parameters":[{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EblTransferOwnersReqDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResponseWrapperUnsignedTxRespDto"}}}}}}}}}
```
