Build with Mesh
One platform for payments, marketplace APIs, and embedded commerce. Use our REST APIs or SDKs—auth, escrow, and stablecoin payments included.
SDKs & libraries
Official SDKs for Ruby, iOS, Android, JavaScript, and PHP.
API examples
Payments (Mesh Pay) and Marketplace each have their own APIs. Below: one example each. Full reference on the product pages.
Payments – Create a charge
curl https://api.mesh.com/v1/charges \
-u sk_live_xxx: \
-d amount=5000 \
-d currency=usd \
-d wallet_id=wallet_xxxMesh Payments → for more examples and the Ruby SDK.
Marketplace – List listings (public)
curl "https://api.mesh.com/listings/search?limit=20" \
-H "Content-Type: application/json"Mesh Marketplace → for authenticated endpoints and the iOS SDK.
Quickstart
- Set up Supabase Auth – Create a project at supabase.com, enable Auth, and configure your client (email/password, OAuth, etc.).
- Get your JWT – After sign-in, Supabase returns an
access_token. Use it asAuthorization: Bearer <token>. - Create or fetch your profile – Call
POST /userswith profile data. The endpoint is idempotent byauthProviderId. - Start building – Listings, offers, transactions, and escrow are available. See the documentation and API reference for full details.
Auth flow
Mesh uses Supabase Auth for identity. The mesh-core API validates JWTs issued by Supabase.
1. Client signs in with Supabase (email/password, OAuth, etc.) 2. Supabase returns a JWT (access_token) 3. Client sends requests with: Authorization: Bearer <token> 4. mesh-core validates the JWT and maps 'sub' to authProviderId 5. On first request, POST /users creates the internal User profile
GET /listings) are public. Protected routes require a valid JWT; invalid or missing tokens return 401 Unauthorized.SDK examples
Use the API with standard fetch or any HTTP client. All requests use JSON; auth is via Bearer token.
List public listings
const res = await fetch(`${API_URL}/listings/search?limit=20`);
const { data } = await res.json();Create user profile (idempotent)
const res = await fetch(`${API_URL}/users`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
},
body: JSON.stringify({
displayName: 'Jane',
email: 'jane@example.com',
}),
});Submit an offer
const res = await fetch(`${API_URL}/offers`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
},
body: JSON.stringify({
listingId: 'listing-uuid',
message: 'I can pick up today',
amountCents: 5000,
}),
});Generic API helper (recommended)
async function api(path, { method = 'GET', body, token } = {}) {
const res = await fetch(`${API_URL}${path}`, {
method,
headers: {
'Content-Type': 'application/json',
...(token && { Authorization: `Bearer ${token}` }),
},
body: body ? JSON.stringify(body) : undefined,
});
if (!res.ok) throw new Error(await res.text());
return res.status === 204 ? {} : res.json();
}
// Usage
const listings = await api('/listings/search?limit=10');
const user = await api('/users', { method: 'POST', body: { displayName: 'Jane' }, token });Escrow flow (summary)
Escrow uses Stripe Payment Intents. After offer acceptance, the buyer funds escrow; funds are released only after both parties confirm the exchange.
POST /escrow/create-payment-intentwithtransactionId→ returnsclientSecret- Confirm payment client-side with Stripe.js
- Webhook updates transaction to
ESCROW_FUNDED - Schedule exchange, both confirm →
POST /escrow/release/:transactionId
See documentation, API Docs, and the mesh-core docs/escrow-flow.md for full details.