Pipe17 exchanges data with third-party systems through connectors. A connector is the code that connects to a vendor's API and converts data between the app's canonical format and the vendor's format. A merchant adds an instance of a connector to their organization as an integration. Think of a connector as a class definition and an integration as an instance of that class.
A custom integration combines the connector and the integration into one. It is backed by a private connector that has a single integration instance, available only in the organization where you create it. In this series, "custom connector," "custom connection," and "custom integration" all mean the same thing.
This chapter shows you how to:
- Create a custom 3PL integration in the app.
- Choose the entity flows your integration supports.
- Save the API keys your integration code needs.
- Complete the connector setup through the API, including credentials and mappings.
Before you begin
- You need admin permissions in your organization to create integrations.
- Have a secure place ready to store API keys, such as a password manager or secrets vault.
How entity flows work
Entity flows define which data your integration exchanges with the app, and in which direction. Directions are always described from the app's point of view:
- Pull in: Your external system creates or updates this entity in the app. For example, a 3PL pulls in Fulfillments after it ships an order.
- Push out: Your external system reads this entity from the app. For example, a 3PL reads Shipping Requests to learn which orders to ship.
When you select an Integration type, the app preselects a recommended set of entity flows. You can adjust the selection before you create the integration.
| Integration type | Preselected flows | Pull in | Push out |
|---|---|---|---|
| Ecommerce | 5 | Orders, Products, Locations | Fulfillments, Inventory |
| Ecommerce with advanced permissions | 8 | Orders, Fulfillments, Inventory, Products, Locations | Orders, Fulfillments, Inventory |
| Fulfillment | 5 | Fulfillments, Inventory, Locations | Shipping Requests, Products |
| Fulfillment with advanced permissions | 10 | Orders, Shipping Requests, Fulfillments, Inventory, Locations | Orders, Shipping Requests, Fulfillments, Inventory, Products |
| Other | 0 | None | None |
For a 3PL integration, select Fulfillment. The default Fulfillment preset covers the core 3PL workflow: read Shipping Requests and Products from the app, and send Fulfillments, Inventory, and Locations to the app.
Add a custom integration
- Navigate to Integrations and select Add custom integration.
- In Integration Info, enter a Name for the integration.
- Optionally, enter a Description and upload a Logo. The logo must be a JPEG or PNG file, 1 MB or smaller.
- In Access Scope, leave Allow this integration to read entity records from other integrations cleared unless your integration must read records that other integrations create. For details, see the organization-wide access section later in this article.
- In Entity Flow Capabilities, select Fulfillment as the Integration type.
- Optionally, select Enable advanced permissions to add two-way flows for Orders, Shipping Requests, Fulfillments, and Inventory.
- Review the entity flow table. Select Pull in or Push out for any additional entities your integration supports, and clear any it does not. To restore the preset, select Reset to defaults.
- Expand Advanced (optional) and enter a Version, such as 1.0.0. Optionally, enter a Documentation URL and webhook details.
- Optionally, in README (optional), enter setup instructions for the admins who will configure this integration. Markdown formatting is supported.
- Select Create Integration.
- In the Integration Created dialog, select Copy next to the Integration API Key and the Connector API Key, and store both keys securely.
- Select View integration to open the new integration.
The custom integration now appears in your Integrations list and is available only to your organization.
Fields in the Add Custom Integration dialog
| Section | Field | Description | Default |
|---|---|---|---|
| Integration Info | Name | Name shown in the Integrations list. Required. | Empty |
| Integration Info | Description | Short description of the integration. | Empty |
| Integration Info | Logo | JPEG or PNG image, 1 MB maximum. | None |
| Access Scope | Allow this integration to read entity records from other integrations | Grants organization-wide read access for the selected entities. | Cleared |
| Entity Flow Capabilities | Integration type | Ecommerce, Fulfillment, or Other. Sets the preselected entity flows. Required. | Ecommerce |
| Entity Flow Capabilities | Enable advanced permissions | Adds two-way flows to the Ecommerce or Fulfillment preset. | Cleared |
| Entity Flow Capabilities | Entity flow table | Pull in and Push out selections for each entity. | Based on Integration type |
| Advanced (optional) | Version | Connector version, such as 1.0.0. | Empty |
| Advanced (optional) | Documentation URL | Link to your integration documentation. | Empty |
| Advanced (optional) | Webhook URL | Endpoint that receives webhook events. | Empty |
| Advanced (optional) | Webhook API Key | Key the app sends with each webhook request. | Empty |
| Advanced (optional) | Webhook Topics | Events that trigger a webhook, such as shipments, fulfillments, or inventory. | None |
| README (optional) | Markdown editor | Setup instructions shown on the integration page. | Empty |
What the app sets up for you
When you create the integration, the app also completes the following setup:
- Status: The integration is created with the status Connected.
- Settings toggles: Each selected entity flow gets an on/off toggle on the integration's Settings tab. All toggles are off by default. An admin turns on the flows to run, and your integration code must check these settings before it syncs data. For more information, see Chapter 3.
- API key permissions: The Integration API Key can create, read, update, delete, and list each Pull in entity, and read, update, and list each Push out entity.
-
Capabilities: The app adds a capability for each entity flow, such as
fulfillments:inandshipments:out. - Connector name: The app names the connector "[Integration name] Connector."
Your API keys
The app generates two keys for a custom integration. Both are also available later on the integration's API Key tab.
| Key | Use it to |
|---|---|
| Integration API Key | Exchange data with the app, such as reading Shipping Requests and creating Fulfillments. Your integration code uses this key day to day. |
| Connector API Key | Read and update the connector definition through the Connection API, such as adding credential fields or mappings. |
Store both in a secrets manager or environment variables, never in source code. Every request sends the key in the X-Pipe17-Key header.
export PIPE17_BASE_URL="https://api-v3.pipe17.com/api/v3" export PIPE17_INTEGRATION_KEY="<your Integration API Key>" export PIPE17_CONNECTOR_KEY="<your Connector API Key>"
The create dialog sets up the basics. Credential fields, mappings, custom settings and some access options are set afterwards on the connector itself, with the Connector API Key. The connector is the template; every customer's integration is an install of it.
Step 1 – Find your connector ID.
curl -s "$PIPE17_BASE_URL/connectors" \ -H "Accept: application/json" \ -H "X-Pipe17-Key: $PIPE17_CONNECTOR_KEY"
Note the connectorId in the response. Every later change to the connector uses it. Save the full response too: you will send parts of it back in Step 2.
Step 2 – Add connection fields and entity mappings. Connection fields are the credentials a customer enters for your system (an API token, an account ID). entities lists every flow with its mapping.
curl -s -X PUT "$PIPE17_BASE_URL/connectors/<connectorId>" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-Pipe17-Key: $PIPE17_CONNECTOR_KEY" \
-d '{
"connection": {
"type": "basic",
"fields": [
{
"path": "wmsApiToken",
"type": "string",
"secret": true,
"options": { "label": "WMS API access token" }
}
]
},
"entities": [
{ "name": "shipments", "direction": "out", "mappingUuid": "<mapping uuid>" },
{ "name": "fulfillments", "direction": "in", "mappingUuid": "<mapping uuid>" },
{ "name": "inventory", "direction": "in", "mappingUuid": "<mapping uuid>" },
{ "name": "locations", "direction": "in", "mappingUuid": "<mapping uuid>" },
{ "name": "products", "direction": "out", "mappingUuid": "<mapping uuid>" }
]
}'Customers enter the connection field values when they set up the integration. Your connector reads them from the integration's connection.fields. Mark anything sensitive "secret": true so it is masked in the app.
Mappings. Each flow's mappingUuid points to a mapping: the rules that translate fields between Pipe17's schema and your system's (for example, which of your fields becomes Pipe17's order ID). Mappings are covered in their own guide, Customizing mappings in Pipe17.
Important: entities replaces the existing list. Send every flow your connector supports in each call; any flow you leave out is removed. Take the current values from the Step 1 response.
Optional settings on the connector
| Property | What it does |
|---|---|
settings.fields |
Adds your own configuration options to the integration's Settings tab, for example a SKU filter. See Add your own settings in Chapter 3 |
capability |
Extra actions beyond the default flows. The app adds one per flow automatically (for example shipments:out, fulfillments:in). Add others only if you need them, for example shipments_cancel_in if your system can cancel Shipping Requests |
orgWideAccess |
true gives the integration read access to records created by other integrations. Same as the Access Scope option in the create dialog |
version |
The connector version. Set one when you create the integration (for example 1.0.0) |
readme |
Setup instructions shown to customers, in Markdown |
Versions and upgrades. Changes to Access Scope or entity flows reach an existing integration (and its API key) only after the integration is upgraded. Raise the Version in the integration's Advanced section, save, then open a support ticket asking Pipe17 to apply the upgrade. If the version was left empty, the app cannot offer an upgrade, so always set one at creation.
Regenerated keys. If you regenerate either key on the API Key tab, update it everywhere your connector stores it.
First calls
Read your integration record and settings with the Connector API Key:
curl -s "$PIPE17_BASE_URL/integrations" \ -H "X-Pipe17-Key: $PIPE17_CONNECTOR_KEY"
List Shipping Requests waiting for fulfillment with the Integration API Key:
curl -s -G "$PIPE17_BASE_URL/shipping_requests" \ -H "X-Pipe17-Key: $PIPE17_INTEGRATION_KEY" \ --data-urlencode "status=readyForFulfillment" \ --data-urlencode "count=10"
Get sample records from your sandbox. Before you write any mapping code, pull a few complete records and keep them as fixtures. They show every field your connector will receive.
curl -s -G "$PIPE17_BASE_URL/shipping_requests/<shipmentId>" \ -H "X-Pipe17-Key: $PIPE17_INTEGRATION_KEY" \ --data-urlencode "keys=*" > sample-shipping-request.json curl -s -G "$PIPE17_BASE_URL/products" \ -H "X-Pipe17-Key: $PIPE17_INTEGRATION_KEY" \ --data-urlencode "count=5" \ --data-urlencode "keys=*" > sample-products.json
If your sandbox has no Shipping Requests yet, place a test order (Chapter 9) and route it to one of your locations.
A successful response has "success": true and a list named after the record (integrations, shipments). An error has "success": false, a code and a message.
A minimal API client
Every later example uses this helper. Save it as p17.js.
// p17.js – minimal Pipe17 API client (Node.js 18+)
const BASE = process.env.PIPE17_BASE_URL ?? 'https://api-v3.pipe17.com/api/v3';
export async function p17(method, path, { key = process.env.PIPE17_INTEGRATION_KEY, query, body } = {}) {
const url = new URL(BASE + path);
for (const [name, value] of Object.entries(query ?? {})) {
if (value === undefined) continue;
// List filters are sent comma-separated, e.g. status=fulfilled,partialFulfillment
url.searchParams.set(name, Array.isArray(value) ? value.join(',') : String(value));
}
const res = await fetch(url, {
method,
headers: { 'X-Pipe17-Key': key, 'Content-Type': 'application/json' },
body: body === undefined ? undefined : JSON.stringify(body),
});
const data = await res.json().catch(() => ({}));
if (!res.ok || data.success === false) {
const err = new Error(data.message ?? `Pipe17 HTTP ${res.status}`);
err.status = res.status;
err.body = data;
throw err;
}
return data;
}Query conventions that apply to every list endpoint: count (page size, default 100) and skip (offset); keys to choose which top-level fields come back (* for all); order to sort; since/until to filter by creation time and updatedSince/updatedUntil to filter by last update, as RFC 3339 timestamps.
Best practices
- Set a version at creation. If the Version field is empty, the app cannot offer an upgrade later, and changes to access or entity flows cannot take effect.
- Start from the preset. The Fulfillment preset covers the core 3PL workflow. Add flows only when your integration code handles them.
- Turn on flows in Settings. Settings toggles are off by default. Confirm the right flows are on before you go live.
- Store both keys immediately. Save the Integration API Key and the Connector API Key before you close the Integration Created dialog.
Troubleshooting
-
The Create Integration button is unavailable
Name and Integration type are required. Enter a name and select an integration type. -
The integration does not sync data after creation
Settings toggles for each entity flow are off by default. Open the integration's Settings tab and turn on the flows your integration supports. -
An API call returns an authorization error
Confirm you are using the correct key. Use the Connector API Key for Connection API calls and the Integration API Key for data calls. If a key was regenerated, update your systems with the new key. -
Changes to Access Scope or entity flows have no effect
These changes apply only after the version is raised and the integration is upgraded. Confirm you raised the Version, and then contact support to apply the upgrade.
Need Help?
If you need additional assistance:
- Use Ask Pippen, our AI agent, located at the top of the app page.
- Submit a support request with as much relevant detail as possible. Learn how to submit a request.
We're here to help you succeed with your operations.
Comments
0 comments