Skip to main content

Overview

The intents endpoint allows wallets to resolve a proposal by transaction ID. This is used when a buyer scans a QR code or clicks a payment link.
This endpoint is public and does not require authentication.

Endpoints

Get Proposal by Transaction ID

Resolve a proposal by its transaction ID.
GET /api/identipay/v1/intents/:txId
Per the whitepaper (section 6), this endpoint is available at:
https://<hostname>/api/identipay/v1/intents/<transaction-id>

Path Parameters

txId
string
required
Transaction ID (UUID) from the payment URI or QR code

Response

Returns the full CommerceProposal JSON-LD object (see Proposals for schema).
@context
string
JSON-LD context (https://schema.identipay.net/v1)
@type
string
Type (CommerceProposal)
transactionId
string
UUID for this transaction
merchant
object
Merchant information
items
array
Array of line items
amount
object
Total amount and currency
deliverables
object
Receipt and warranty information
constraints
object
Age gate or region restrictions
expiresAt
string
ISO 8601 expiry timestamp
intentHash
string
Hash for on-chain verification
settlementChain
string
Blockchain name (sui)
settlementModule
string
On-chain settlement module address

Example Request

curl https://api.identipay.com/api/identipay/v1/intents/550e8400-e29b-41d4-a716-446655440000

Example Response

{
  "@context": "https://schema.identipay.net/v1",
  "@type": "CommerceProposal",
  "transactionId": "550e8400-e29b-41d4-a716-446655440000",
  "merchant": {
    "did": "did:identipay:acme.com:...",
    "name": "Acme Store",
    "suiAddress": "0xabc123...",
    "publicKey": "a1b2c3d4..."
  },
  "items": [
    {
      "name": "Coffee",
      "quantity": 2,
      "unitPrice": "5.00"
    }
  ],
  "amount": {
    "value": "10.00",
    "currency": "USDC"
  },
  "deliverables": {
    "receipt": true,
    "warranty": {
      "durationDays": 30,
      "transferable": false
    }
  },
  "constraints": {
    "ageGate": 21
  },
  "expiresAt": "2026-03-09T21:15:00.000Z",
  "intentHash": "a1b2c3d4e5f6...",
  "settlementChain": "sui",
  "settlementModule": "0x123abc::settlement"
}

Error Responses

Implementation Details

Resolution Flow

When a wallet resolves an intent (see routes/intents.ts:12-42):
  1. Lookup Proposal: Query database by transaction ID
  2. Check Existence: Return 404 if not found
  3. Check Expiry: If expired, update status and return error
  4. Check Status: Return error if cancelled
  5. Return Proposal: Return full proposal JSON

Automatic Expiry Detection

The endpoint checks expiry on every request:
if (new Date(proposal.expiresAt) < new Date()) {
  if (proposal.status === "pending") {
    await db
      .update(proposals)
      .set({ status: "expired" })
      .where(eq(proposals.transactionId, txId));
  }
  throw new ValidationError("Proposal has expired");
}
This ensures proposals cannot be settled after expiry, even if the background expiry task hasn’t run yet.

Payment URI Format

Wallets typically extract the transaction ID from a payment URI:
identipay://{merchant-hostname}/{transaction-id}
Example:
identipay://acme.com/550e8400-e29b-41d4-a716-446655440000
The wallet:
  1. Extracts the hostname (acme.com)
  2. Extracts the transaction ID (550e8400-...)
  3. Constructs the intent URL: https://acme.com/api/identipay/v1/intents/550e8400-...
  4. Fetches the proposal
  5. Displays it to the user for approval

Privacy Considerations

The proposal includes the merchant’s Sui address and public key, but:
  • Does NOT include the buyer’s information (added during settlement)
  • Does NOT reveal which addresses are scanning the proposal
  • Can be fetched anonymously (no authentication required)

Settlement Workflow

After resolving the proposal, the wallet:
  1. Display Proposal: Show merchant, items, amount, constraints
  2. Check Constraints: Verify age gate (generate ZK proof if needed)
  3. Build Settlement: Create settlement transaction via /transactions/gas-sponsor
  4. Sign & Submit: Sign transaction and submit via /transactions/submit
  5. Monitor Status: Watch for settlement confirmation via WebSocket
See Transactions for settlement details.

Build docs developers (and LLMs) love