Host and login endpoints
API reference
Routes run on two trust boundaries in this deployment. POST /api/challenges and POST /api/verify are host-origin routes that a third-party integrator must implement. Enrollment, witness, eligibility, and health routes run on the VeilPass login service. GET /api/session is a host-side demo adapter, not an SDK requirement.
Host POST /api/challenges
This route belongs to the integrating host origin. Accept a strict JSON body containing gateId, derive/validate origin against trusted configuration, issue at least 32 cryptographically random bytes, bind the challenge digest, gate, exact origin and five-minute expiry durably, and return HTTP 201 with Cache-Control: no-store. Reject invalid input with a safe code; return 403 for an untrusted origin and 503 if the durable store is unavailable. The browser SDK calls this route after the popup is ready.
Request
{"gateId":"premium-holder"}
ChallengeResponse (201)
{"challengeId":"<uuid>","challenge":"<base64url-random-value>","origin":"https://app.example","gateId":"premium-holder","expiresAt":"<ISO-8601>"}Host POST /api/verify
This route also belongs to the host. It receives the sensitive proof request, enforces strict schema and size limits, derives origin/gate policy server-side, invokes the actual verifier, and consumes challenge plus nullifier atomically. On success only, it creates the host's opaque server session. Return Cache-Control: no-store.
Success: 200
{"ok":true,"eligible":true,"privateAppId":"<origin-scoped-id>","gateId":"premium-holder","epoch":1,"origin":"https://app.example","expiresAt":"<ISO-8601>"}
Failure: 400 (or 403/503 by policy)
{"ok":false,"error":"PROOF_INVALID","requestId":"<opaque-request-id>"}POST /api/verify payload
The strict ProofResult carries challengeId, proof bytes, and publicInputs: gateId, epoch, origin, challengeHash, credentialCommitment, credentialRoot, privateAppId, loginNullifier, revocationHash, proofCreatedAt, and proofExpiresAt. No Stellar wallet address is part of this contract. The proof/public inputs are sensitive and must not be logged or persisted.
Endpoint behavior in this repository
The Next.js example route accepts at most 2,000,000 bytes for proof submission, returns HTTP 200 on success, HTTP 403 for origin mismatch, HTTP 503 for service/capacity failures, and HTTP 400 for expected invalid proof or policy failures. It emits Cache-Control: no-store. An integration may choose a different response mapping only if it preserves the strict JSON error contract, safe diagnostics, no-store behavior, and client compatibility.
GET /api/session
This is the example application's host-only session endpoint, not a required VeilPass SDK route. It reads a host-only vp_session cookie and returns 200 { authenticated: true, privateAppId, gateId } for a valid session; otherwise it returns 401 { authenticated: false }. Both results use Cache-Control: no-store. Production integrators should implement their own session lifecycle and CSRF policy.
POST /api/credentials/witness
Refreshes the signed credential's Merkle witness against the active contract root. It is part of the hosted-login service, not an endpoint a host dApp needs to call directly.
Enrollment and witness routes
POST /api/enrollment/challenge checks an allowed gate, resolves the exact login origin, and checks the public wallet's configured Testnet eligibility before issuing a challenge. POST /api/enrollment/issue verifies the Freighter message signature, consumes the challenge, issues a credential, updates the durable Merkle tree and publishes the new root through the gate-owner service. POST /api/credentials/witness validates the issuer signature and returns a refreshed witness for the active root. These are VeilPass issuer endpoints; host dApps must not call them as a substitute for host challenge/verify routes. Request/response bodies contain sensitive holder data and use no-store.
POST /api/enrollment/eligibility
Checks a public Stellar address against the configured eligibility rule on the login service. This is an enrollment preflight; it is not called by the host SDK and its result is not a login proof.
GET /api/session
The demo-host session endpoint returns 200 with { authenticated: true, privateAppId, gateId } or 401 with { authenticated: false }. It reads only the opaque host cookie. This route is example application behavior, not a route the SDK requires at loginOrigin.
GET /api/health
Returns readiness status and stable issue codes only; it must never expose configuration values or secrets. A healthy response is useful operational evidence, but it does not prove that Freighter enrollment, the live proof, or the durable tree/chain state is correct.
Demo-asset fixture and proof simulation
POST /api/demo-asset/challenge and POST /api/demo-asset/issue exist only for the fixed Testnet demo asset fixture and enforce wallet/origin binding and one-time claim limits. POST /api/proof/simulate is a clearly labeled non-production compatibility fixture. Production requests to simulation are rejected and /api/verify never accepts simulated proof output. Neither feature is a general faucet, payment API, or production auth path.
Endpoint ownership summary
On each integrating host origin: POST /api/challenges and POST /api/verify are mandatory host-owned routes; GET /api/session is optional host session behavior. On login.veilpass.dev: POST /api/enrollment/eligibility, POST /api/enrollment/challenge, POST /api/enrollment/issue, POST /api/credentials/witness, and GET /api/health; Testnet-only POST /api/demo-asset/challenge and POST /api/demo-asset/issue; non-production POST /api/proof/simulate. Never send a login-service or issuer secret to a host browser.