Use this file to discover all available pages before exploring further.
Build a seamless, zero-configuration integration between your app and Appstle Memberships. Once connected, your app gets a scoped API token for each merchant — no manual key exchange needed.
Why become a partner?
Frictionless merchant onboarding — one-click connect from either dashboard
No API paywall — merchants don’t need a paid API plan to use your integration
Scoped tokens — each merchant gets an isolated API key; revocable at any time
Automatic cleanup — when a merchant disconnects or uninstalls, access is revoked instantly
The Partner Integration Framework uses a secure handshake protocol. Either side — your app or Appstle — can initiate the connection. Both flows end with your app receiving a scoped API token.
Merchant approval: When your app initiates a connection (Flow A), the merchant must approve it from their Appstle dashboard before you receive an API token. When the merchant initiates from Appstle’s side (Flow B), the connection is approved instantly because the merchant is the one clicking “Connect.”
To get started, reach out to the Appstle team at support@appstle.com with the information below. Our team will set up your partner account and send you your credentials.
Your app or company name. Displayed to merchants when they browse available partner integrations in the Appstle dashboard.
SearchPie
2
Partner ID
Yes
A unique, lowercase slug that identifies your app in API URLs. Use only lowercase letters and hyphens. Once set, this cannot be changed.
search-pie
3
Base URL
Yes
The HTTPS base URL where Appstle will send callback requests (connect, verify, approved). Must be publicly accessible — Appstle will not call HTTP or localhost URLs.
https://api.searchpie.com
4
Contact Email
Yes
The email address where we’ll send your Partner Secret and any onboarding follow-ups. Use a team email if possible — the secret is shown only once.
dev-team@searchpie.com
5
Authentication Mode
Optional
How your API calls are authenticated. Choose one: Partner Secret (simpler — pass secret in a header) or HMAC-SHA256 (more secure — sign each request). Defaults to Partner Secret if not specified. See Step 1b for details.
Partner Secret
6
Connect Mode
Optional
How merchant connections are established. Choose one: Nonce Handshake (full two-way verification — you receive an Appstle API key) or Simple Token Exchange (streamlined — you provide your own token for Appstle to call your API). Defaults to Nonce Handshake if not specified. See Step 1c for details.
Nonce Handshake
7
Custom Endpoint Paths
Optional
By default, Appstle calls /appstle/connect and /appstle/verify on your Base URL. If you need different paths (e.g., /webhooks/appstle/connect), specify them here.
/webhooks/appstle/connect
8
Sync Path
Optional
If you want Appstle to push membership data to your app (e.g., when memberships are created, cancelled, or plans change), provide the path on your server where Appstle should send these payloads. See Data Sync for details.
/appstle/sync
9
App Logo
Optional
A square logo (PNG or SVG, at least 128×128px) displayed next to your app name in the merchant’s Appstle dashboard. If not provided, a placeholder icon is used.
—
Not sure about some of these? Only the first four fields are required to get started. You can always reach out to support@appstle.com to change your authentication mode, connect mode, or add a sync path later.
Your unique identifier, as requested. Becomes part of the API URL.
Partner Secret
xK9mQ2vL... (48 chars)
A secret key used to authenticate your API calls. Treat this like a password.
Base URL
https://membership-admin.appstle.com
Appstle’s API base URL. Same for all partners.
Your Partner Secret is shown only once during onboarding. Copy it immediately and store it in a secure location (environment variable, secrets manager, etc.). If you lose it, contact Appstle to rotate it — the old secret will be invalidated immediately.
Store your credentials as environment variables:
# .env (never commit this file)APPSTLE_PARTNER_ID=search-pieAPPSTLE_PARTNER_SECRET=xK9mQ2vLa8nR3pY... # if using Partner Secret authAPPSTLE_HMAC_KEY=your-hmac-key-here # if using HMAC-SHA256 authAPPSTLE_BASE_URL=https://membership-admin.appstle.com
A more secure approach where requests are signed with a shared HMAC key. Instead of sending the secret directly, you compute a signature over the request body.Headers required:
Get the current Unix timestamp (seconds, not milliseconds)
Concatenate the timestamp and the raw JSON request body: timestamp + body
Compute HMAC-SHA256 of that string using your HMAC key
Send the hex-encoded result in X-Partner-Signature
Timestamp validation: Appstle rejects requests where the timestamp is more than 5 minutes from the server’s current time. Make sure your server clock is synced (NTP).
The full two-way verification flow described in this guide. Both sides verify each other using a one-time nonce. After the handshake, your app receives an Appstle API key (apst_...) to call Appstle’s External API.Best for: partners who want to read/write data in Appstle (membership contracts, plans, billing, etc.)
A streamlined flow where your app sends its own access token to Appstle (or Appstle calls your connect endpoint and you return one). No nonce, no verify endpoint needed. Appstle stores your token and uses it to call your API when needed.Best for: partners where Appstle needs to call the partner’s API (e.g., syncing data to the partner’s platform), rather than the partner calling Appstle’s API.Key difference from Nonce Handshake: in Simple Token Exchange, your app provides its own access token to Appstle. Appstle stores this token and uses it to push data to your API (via your sync_path — see Data Sync below). Your app does not receive an Appstle API key in this mode.
Need both directions? If you need to both push data to Appstle AND have Appstle push data to you, use the Nonce Handshake mode and provide a sync_path during onboarding. Contact support@appstle.com to discuss your use case.
How Simple Token Exchange works.Partner-initiated:
Your access_token is stored securely but will not be activated until the merchant approves the connection from their Appstle dashboard. Once approved, Appstle calls your /appstle/approved endpoint to confirm (see Handling the approval callback).
Appstle-initiated: Appstle calls your /appstle/connect endpoint with { "shop_domain": "..." }. Your app responds with:
With Simple Token Exchange, your app does NOT receive an Appstle API key. If you also need to call Appstle’s External API, use the Nonce Handshake mode instead.
A nonce (number used once) is a random, single-use string that proves both sides of the connection are who they claim to be. It prevents replay attacks and ensures the handshake can’t be forged.
Your app must expose two HTTP endpoints that Appstle calls during the connection handshake. The paths default to /appstle/connect and /appstle/verify but can be customized during onboarding.Both endpoints must:
Accept POST requests with a JSON body
Return JSON responses
Be accessible over HTTPS (Appstle will not call HTTP endpoints)
Respond within 10 seconds (or the request will time out)
The merchant’s Shopify domain (e.g. cool-store.myshopify.com)
app
string
Always "memberships" — identifies which Appstle app is connecting
callback_url
string
The exact URL your app must call to complete the handshake
callback_nonce
string
A one-time-use token generated by Appstle. Expires in 5 minutes.
What should your app do?
Validate the shop — check that this shop_domain exists in your system. If you don’t recognize the shop, return an error.
Store the nonce and callback URL — save callback_nonce and callback_url associated with this shop_domain. You’ll need them to complete the handshake.
Call back to Appstle — either immediately (auto-approve) or after merchant confirmation, call the callback_url to complete the connection. See Completing the handshake below.
Return a success response — any 2xx status code tells Appstle the request was received.
Node.js (Express)
const express = require('express');const axios = require('axios');const router = express.Router();router.post('/appstle/connect', async (req, res) => { const { shop_domain, app, callback_url, callback_nonce } = req.body; // 1. Validate: does this shop exist in your system? const shop = await db.shops.findOne({ domain: shop_domain }); if (!shop) { return res.status(400).json({ error: 'Shop not found in our system' }); } // 2. Store the nonce and callback URL for this shop await db.pendingConnections.upsert({ shopDomain: shop_domain, callbackUrl: callback_url, callbackNonce: callback_nonce, createdAt: new Date(), expiresAt: new Date(Date.now() + 5 * 60 * 1000), // 5 minutes }); // 3. Option A: Auto-approve (call back immediately) try { const response = await axios.post(callback_url, { shop_domain: shop_domain, callback_nonce: callback_nonce, }, { headers: { 'X-Partner-Secret': process.env.APPSTLE_PARTNER_SECRET, 'Content-Type': 'application/json', }, }); if (response.data.verified && response.data.access_token) { // 4. Store the access token for this merchant await db.appstleTokens.upsert({ shopDomain: shop_domain, accessToken: response.data.access_token, connectedAt: new Date(), }); } } catch (err) { console.error('Failed to complete Appstle handshake:', err.message); } // 5. Return success to Appstle res.json({ success: true });});
When is this called? Appstle calls this when a merchant initiates the connection from your app’s dashboard (Flow A). Appstle is asking your app: “Did you actually send this nonce?”What does it receive?
This is the flow where the merchant clicks “Connect Appstle” in your dashboard.
1
Merchant clicks "Connect Appstle" in your dashboard
The merchant initiates the connection from inside your app’s UI.
2
Your app generates a cryptographically random nonce
Store it keyed by shop_domain with a 5-minute TTL.
3
Your app calls POST /api/partner/{id}/connect
Send the shop_domain, the callback_nonce, and your Partner Secret.
4
Appstle validates your Partner Secret
Appstle also confirms the shop has Appstle Memberships installed.
5
Appstle calls YOUR /appstle/verify endpoint
Payload: the shop_domain and the same callback_nonce.
6
Your /appstle/verify checks the nonce
Confirm it matches, delete it, return { "verified": true }.
7
Appstle returns pending_merchant_approval
The connection is pending — no access token has been issued yet.
8
Merchant approves in their Appstle dashboard
They open Settings → Partner Connections and click Approve.
9
Appstle creates a scoped API key
The token is POSTed to YOUR /appstle/approved endpoint.
10
Your app stores the access_token
Show “Connected!” to the merchant. You’re done.
Full implementation (Node.js):
const crypto = require('crypto');const axios = require('axios');const PARTNER_ID = process.env.APPSTLE_PARTNER_ID;const PARTNER_SECRET = process.env.APPSTLE_PARTNER_SECRET;const APPSTLE_BASE = process.env.APPSTLE_BASE_URL; // https://membership-admin.appstle.com// Called when merchant clicks "Connect Appstle" in your dashboardasync function connectToAppstle(shopDomain) { // Step 2: Generate a cryptographically random nonce const nonce = crypto.randomBytes(32).toString('hex'); // Store it so your /appstle/verify endpoint can look it up later await storeNonce(shopDomain, nonce); // see nonce storage examples above // Step 3: Call Appstle's partner connect endpoint const response = await axios.post( `${APPSTLE_BASE}/api/partner/${PARTNER_ID}/connect`, { shop_domain: shopDomain, callback_nonce: nonce, }, { headers: { 'X-Partner-Secret': PARTNER_SECRET, 'Content-Type': 'application/json', }, } ); // Steps 4-6 happen automatically (Appstle calls your /appstle/verify) // Step 7: Appstle returns pending status — token is NOT delivered yet const { status } = response.data; if (status === 'pending_merchant_approval') { // The merchant needs to approve in their Appstle dashboard. // Once approved, Appstle will POST the token to your /appstle/approved endpoint. await markConnectionPending(shopDomain); return { pending: true }; } throw new Error('Connection failed');}
What happens next? The merchant will see a “Pending Request” in their Appstle dashboard under Settings → Partner Connections. (This menu appears automatically once a partner initiates a connection request — it is not visible before any partner has connected.) When they click “Approve,” Appstle creates a scoped API key and delivers it to your /appstle/approved endpoint (see Handling the approval callback below). Pending requests expire after 30 days if not acted on.
Deep link to approval screen: You can redirect the merchant directly to the approval screen to minimize friction:
Replace {shop-handle} with the merchant’s store handle (the part before .myshopify.com). This takes them straight to the pending connection for one-click approval. You can trigger this redirect in your UI immediately after receiving the pending_merchant_approval response.
After a successful connection, your app has an access_token (prefixed with apst_). For Appstle-initiated connections (Flow B), the token is returned immediately in the verify response. For partner-initiated connections (Flow A), the token is delivered asynchronously to your /appstle/approved endpoint after the merchant approves (see Handling the approval callback below).Use this token exactly like a merchant API key — pass it in the X-API-Key header:
curl -X GET \ "https://membership-admin.appstle.com/api/external/v2/subscription-contract-details?shop=cool-store.myshopify.com" \ -H "X-API-Key: apst_AbCdEfGhIjKlMnOpQrStUvWxYz123456789012"
Some integrations work best when Appstle pushes data to your app, rather than your app pulling from Appstle’s API. For example, an analytics platform might need Appstle to push membership data so it can be tracked alongside other store metrics.
During onboarding, you can configure a sync_path on your server (e.g., /appstle/sync). When membership events occur (memberships created, cancelled, billing attempts, plan changes, upgrades/downgrades), Appstle calls your endpoint with the relevant data.
Config field
Example
Description
sync_path
/appstle/sync
Your endpoint where Appstle pushes membership data
When Appstle calls your endpoints, it authenticates using the auth mode configured for your partner:
Partner Secret mode: no additional headers (your endpoints are responsible for validating the source — consider IP allowlisting)
HMAC-SHA256 mode (recommended): Appstle signs every request with X-Partner-Timestamp and X-Partner-Signature headers. Your app should verify the HMAC signature to confirm the request came from Appstle.
Verifying incoming HMAC signatures (Node.js):
const crypto = require('crypto');function verifyAppstleSignature(req, hmacKey) { const timestamp = req.headers['x-partner-timestamp']; const signature = req.headers['x-partner-signature']; if (!timestamp || !signature) return false; // Reject if timestamp is more than 5 minutes old const now = Math.floor(Date.now() / 1000); if (Math.abs(now - parseInt(timestamp)) > 300) return false; // Compute expected signature const data = timestamp + req.rawBody; // make sure you capture raw body const expected = crypto .createHmac('sha256', hmacKey) .update(data) .digest('hex'); // Constant-time comparison return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(signature) );}
If you configure a disconnect_path during onboarding (e.g., /appstle/disconnect), Appstle will call your endpoint whenever a merchant disconnects — whether they disconnect from the Appstle dashboard, from your app, or by uninstalling Appstle entirely.Request body from Appstle:
{ "shop_domain": "cool-store.myshopify.com"}
If your partner uses HMAC-SHA256 auth, the webhook includes signed headers (X-Partner-Timestamp, X-Partner-Signature) so you can verify it came from Appstle.Your app should:
Mark the connection as disconnected in your database
This is a best-effort notification — your app should also handle 401 responses from the Appstle API as a fallback signal that the connection was revoked.
Partner-initiated connect is awaiting merchant approval
rejected
Merchant rejected the connection request
expired
The pending request expired (30-day window) — partner must initiate a new connection
not_connected
No connection exists for this partner + shop
Use the status endpoint to poll for approval if your app doesn’t implement the /appstle/approved callback. Poll every 30–60 seconds after initiating a connect. Once the status changes from pending_merchant_approval to active, your token has been delivered via the approval callback (or you can request it again).
When a merchant approves a partner-initiated connection, Appstle delivers the API token by calling an endpoint on your server. This applies to partner-initiated connections only — Appstle-initiated connections (Flow B) return the token immediately.
The path defaults to /appstle/approved but can be customized during onboarding (configured as approval_callback_path).
Your /appstle/approved endpoint must accept unauthenticated POST requests from Appstle’s servers. Do not put authentication middleware (e.g., JWT validation, API key checks) on this endpoint — Appstle will not send your app’s auth credentials when calling this callback. If you need to verify the request is from Appstle, use HMAC-SHA256 authentication mode — when enabled, the callback includes signed headers (X-Partner-Timestamp, X-Partner-Signature) you can verify.
In Simple Token Exchange mode, your app already provided its own token during the connect call. The approval callback simply confirms the connection is now active — Appstle will start using your token for API calls.
Expected response: Return any 2xx status code with a JSON body (e.g., { "success": true }). If your endpoint returns a non-2xx status (e.g., 401 Unauthorized), the connection is still approved on Appstle’s side, but your app won’t know — see What if the callback fails? below.
If your partner uses HMAC-SHA256 auth, the callback includes signed headers (X-Partner-Timestamp, X-Partner-Signature) so you can verify it came from Appstle.
router.post('/appstle/approved', async (req, res) => { const { shop_domain, access_token, status } = req.body; // Optional: verify HMAC signature if using HMAC auth // if (!verifyAppstleSignature(req, HMAC_KEY)) { // return res.status(401).json({ error: 'Invalid signature' }); // } if (access_token) { // Nonce Handshake mode — store the Appstle API token await saveToken(shop_domain, access_token); console.log(`Connection approved for ${shop_domain} — token received`); } else if (status === 'approved') { // Simple Token Exchange mode — our token is now active await markConnectionActive(shop_domain); console.log(`Connection approved for ${shop_domain} — our token is now active`); } res.json({ success: true });});
If your endpoint is unreachable or returns an error, the connection is still approved on Appstle’s side. The API token exists and is valid. Your app can:
Poll the status endpoint — check GET /api/partner/{id}/status?shop_domain=... until the status is active
Retry from Appstle’s side — currently, Appstle does not automatically retry the callback. Contact support if you need the token re-delivered.
If the merchant clicks “Reject,” the connection status changes to rejected and Appstle notifies your app via the disconnect webhook (if configured). Your app should handle this gracefully — show the merchant that the connection was not approved.
Your Partner ID is wrong, or the partner has been deactivated
Double-check your Partner ID. Contact Appstle if unexpected.
TOKEN_INVALID
400
Auth failed: X-Partner-Secret is wrong, or HMAC signature is invalid, or timestamp is >5 min off
Verify your secret or HMAC key. Check for trailing whitespace. For HMAC: ensure server clock is synced (NTP) and you’re signing timestamp + body exactly.
SHOP_NOT_FOUND
400
The shop doesn’t have Appstle Memberships installed
Tell the merchant to install Appstle Memberships first.
ALREADY_CONNECTED
400
An active connection already exists for this partner + shop
Call disconnect first, then reconnect. Or skip — you’re already connected.
VERIFICATION_FAILED
400
Nonce didn’t match, expired (>5 min), or your /verify endpoint returned false
Generate a fresh nonce and try again. Check your nonce storage logic.
NOT_CONNECTED
400
Trying to disconnect or check status, but no active connection exists
The merchant may have already disconnected from their side.
PARTNER_UNREACHABLE
400
Appstle couldn’t reach your /appstle/connect or /appstle/verify endpoint
Check your endpoint URL is correct, HTTPS, and publicly accessible. Check your server logs.
Yes. Each partner gets its own scoped API token. Merchants can connect as many partners as they want. The tokens are completely independent.
What happens if a merchant uninstalls Appstle Memberships?
All active partner connections for that shop are automatically disconnected. Your tokens will stop working (401 responses).
Can I change my partner's permission level (READ_ONLY vs READ_WRITE) after onboarding?
Yes — contact the Appstle team. New connections will use the updated permission, but existing connections keep their original permission until reconnected.
What's the rate limit for partner API calls?
Partner tokens share the same rate limits as regular API keys. If you receive a 429 Too Many Requests, implement exponential backoff.
How do I test the integration before going live?
Use a Shopify development store with Appstle Memberships installed. The partner integration works identically in development and production. You can use a tool like ngrok to expose your local endpoints to the internet for testing.
What if the nonce expires before I can complete the handshake?
The merchant simply needs to click “Connect” again. A new nonce will be generated. Old nonces are automatically cleaned up.
Do I need to implement both Flow A and Flow B?
Yes. Flow A is for when the merchant connects from your dashboard. Flow B is for when they connect from Appstle’s dashboard. Both are needed for a complete integration. You also need the /appstle/approved endpoint to receive API tokens after merchant approval (Flow A).
Can I reconnect a merchant without them doing anything?
No. A new connect handshake requires the merchant to initiate it from one of the dashboards. This is by design — merchants must explicitly authorize each connection.
Why does partner-initiated connect require merchant approval?
For security and trust. When your app initiates a connection, the merchant hasn’t explicitly agreed on Appstle’s side. The approval step ensures merchants consciously grant API access to partner apps. Appstle-initiated connections (Flow B) skip this step because the merchant is already clicking “Connect” in the Appstle dashboard.
How long does a pending approval last?
Pending connection requests expire after 30 days. If the merchant doesn’t approve or reject within that window, the request expires and your app will need to initiate a new connection.
What happens if the merchant rejects the connection?
The status changes to rejected and your app is notified via the disconnect webhook (if configured). The merchant can be asked to reconnect later if they change their mind — your app can initiate a new connection request.