Download OpenAPI specification:
The Supplier Network API (SNAPI) provides programmatic access to Prokeep's messaging platform, enabling suppliers to integrate their systems with Prokeep's communication infrastructure. This API allows suppliers to search for customer groups, retrieve industry information, and send messages to Prokeep users.
SNAPI uses HTTP Basic Authentication with supplier-specific credentials. Each supplier partner is provided with:
All API requests must include an Authorization header with Basic authentication: The resulting header would look like this:
Authorization: Basic {base64_encoded_credentials}
Where {base64_encoded_credentials} is the Base64 encoding of username:password
# Encode credentials
$ echo -n "your_username:your_password" | base64
# Output: eW91cl91c2VybmFtZTp5b3VyX3Bhc3N3b3Jk
# Use in request
$ curl -H "Authorization: Basic eW91cl91c2VybmFtZTp5b3VyX3Bhc3N3b3Jk" \
https://snapi.prokeep.com/v1/groups
SNAPI implements rate limiting to ensure fair usage and system stability. Contact Prokeep support for specific rate limit information for your partner account.
Suppliers can receive real-time updates about message responses through webhooks. When configuring your supplier partner account, you'll provide:
All webhooks include an HMAC signature in the X-Prokeep-Signature header for verification:
# Verify webhook signature (example in Javascript)
const crypto = require('crypto');
/**
* Verifies SNAPI webhook signature according to official specification
*
* @param {string} payload - The raw request body as a string
* @param {string} signature - The X-Prokeep-Signature header value
* @param {string} timestamp - The X-Timestamp header value
* @param {string} secret - Your webhook secret from Prokeep
* @returns {boolean} - True if signature is valid, false otherwise
*/
function verifyWebhookSignature(payload, signature, timestamp, secret) {
if (!signature || !timestamp) {
return false;
}
// Remove sha256= prefix if present
const cleanSignature = signature.startsWith('sha256=') ? signature.slice(7) : signature;
// Create message: timestamp + "." + request_body
const message = timestamp + '.' + payload;
// Calculate HMAC-SHA256
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(message, 'utf8')
.digest('hex');
// Use timing-safe comparison to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(cleanSignature, 'hex'),
Buffer.from(expectedSignature, 'hex')
);
}
// Example usage:
const payload = '{"event":"message.reply","data":{...}}';
const timestamp = req.get('X-Timestamp'); // e.g., "1642253400"
// Check both possible signature headers (one or the other will exist)
const prokeepSignature = req.get('X-Prokeep-Signature');
const xSignature = req.get('X-Signature');
const signature = prokeepSignature || xSignature; // e.g., "sha256=abc123def456..."
const secret = 'your_webhook_secret_here';
const isValid = verifyWebhookSignature(payload, signature, timestamp, secret);
Sent to your configured webhook_url when a Prokeep user replies to a message sent via SNAPI
Verify the X-Prokeep-Signature header before processing: it is sha256= followed by the hex-encoded HMAC-SHA256 of {X-Timestamp}.{raw request body}, computed using your partner webhook secret. Use a timing-safe comparison.
| X-Prokeep-Signature required | string Example: sha256=3f786850e387550fdab836ed7e6dc881de23001b HMAC-SHA256 signature of the payload, prefixed with |
| X-Timestamp required | string Example: 1642253400 Unix timestamp (seconds) the request was signed at. |
| specversion | string |
| id | string <uuid> A unique identifier for this event delivery |
| source | string |
| type | string Value: "com.prokeep.snapi.message.reply" |
object |
{- "specversion": "1.0",
- "id": "20c805d7-9135-4761-a7b8-9ba48d65a35d",
- "type": "com.prokeep.snapi.message.reply",
- "data": {
- "contact_id": "xyz123",
- "sender_contact_id": "ac3f27fd-17dc-4121-8047-07e2a95254c6",
- "first_name": "AAA",
- "last_name": "Administrator",
- "subject": null,
- "body": "Working on it.",
- "attachments": [ ],
- "group_id": "2edca2e4-c6b5-4e8b-841a-fc6a916ebb55"
}
}Search and retrieve Prokeep groups that accept supplier messages.
| q | string Examples:
A JSON-encoded search filter. See the request samples for supported criteria. |
| page-limit | integer <= 25 Default: 25 Maximum number of results to return (max 25). |
| page-after | string Opaque cursor for the next page. |
| page-before | string Opaque cursor for the previous page. |
{- "data": [
- {
- "type": "groups",
- "id": "2edca2e4-c6b5-4e8b-841a-fc6a916ebb55",
- "attributes": {
- "external_id": "external_identifier",
- "name": "Group Name",
- "account": {
- "name": "Account Name"
}, - "address": {
- "address_line_1": "123 Main St",
- "address_line_2": "Suite 100",
- "administrative_district_level_1": "CA",
- "country": "US",
- "locality": "San Francisco",
- "postal_code": "94105"
}, - "business_hours": {
- "monday": {
- "open": "09:00",
- "close": "17:00"
}, - "tuesday": {
- "open": "09:00",
- "close": "17:00"
}
}
}
}
], - "links": {
- "next": "/v1/groups?page-after=g3QAAAABdwRuYW1l",
- "prev": "/v1/groups?page-before=Ghlc2l2ZXMGhlc2l"
}
}Retrieve a list of all available industries in the Prokeep system.
| page-limit | integer <= 50 Default: 50 Example: page-limit=20 Maximum number of results to return (max 50). |
| page-after | string Example: page-after=eyJuYW1lIjoiSFZBQyJ9 Opaque cursor for the next page. |
| page-before | string Opaque cursor for the previous page. |
{- "data": [
- {
- "type": "industry",
- "id": "e6a1b2c3-1234-4a5b-8c9d-0123456789ab",
- "attributes": {
- "name": "HVAC"
}
}
], - "links": {
- "next": "/v1/industries?page-after=g3QAAAABdwRuYW1l",
- "prev": "/v1/industries?page-before=Ghlc2l2ZXMGhlc2l"
}
}Send a message to a Prokeep group on behalf of a contact.
The message details
| group_id required | string <uuid> The ID of an existing group that accepts supplier messages |
| body required | string The message content |
| subject | string or null <= 255 characters An optional subject line |
| attachments | Array of strings <uri> [ items <uri > ] URLs of publicly-reachable attachments. Each URL is validated with a HEAD request and must return a 2xx status. |
required | object (Contact) Contact information femail address. Either email_address or phone_number must be provided. |
{- "group_id": "123e4567-e89b-12d3-a456-426614174000",
- "body": "Hello, I wanted to follow up on your recent inquiry about our new product line.",
- "subject": "New Product Line Follow-up",
- "contact": {
- "id": "supplier_contact_12345",
- "first_name": "John",
- "last_name": "Doe",
- "company": "Acme Supply Co",
- "email_address": "john.doe@acmesupply.com"
}
}{- "status": "accepted",
- "message": "Message queued for processing"
}