# Partners

Read your trading partners and how each one is configured: its connection, its envelopes, its webhooks, the transaction sets it exchanges in each direction, and its flows.

**Preview.** These endpoints are in preview. Their response shapes may change without notice while the configuration model settles.

These endpoints are read-only. Creating and changing partners, connections, envelopes, webhooks, mappings and flows is done in the Tediware application.

Both endpoints cover your whole organization, so both require a standard or read-only API key. Sandbox keys cannot reach them.

## No secrets

Passwords, passphrases, private keys, webhook secrets, sink tokens and API keys are absent from these responses, not masked. A test renders every serializer on this plane through a fully populated record and fails if any key matching those words appears at any depth, so the guarantee holds for the resources added to this plane later as well.

## No verdict is rendered

There is no `ready` flag. You get flow status, whether a mapping or an implementation is attached, and whether a connection is provisioned, and you decide what that means for your integration. Concretely, a transaction set is usable when its setting exists for the direction you need, a mapping or implementation is attached to it, and the flow for that direction has `status: "active"`.

That split is deliberate: a computed flag would have to pick one definition of ready, and a shipping integration, a setup wizard and a monitoring check each want a different one.

## List Partners

```
GET /platform/partners
```

Returns your partners with a summary of what is attached to each, oldest first, so a page reads in the order they were set up.

```json
{
  "partners": [
    {
      "id": "8c2021f8-8310-4628-80f9-b578d4d68e11",
      "key": "ACME",
      "name": "Acme Foods",
      "connection": { "id": "a1b2c3d4-...", "name": "Acme SFTP", "kind": "sftp" },
      "inboundSets": ["810", "850"],
      "outboundSets": ["856", "997"],
      "flows": [
        { "direction": "inbound", "status": "active" },
        { "direction": "outbound", "status": "active" }
      ]
    }
  ],
  "pagination": {
    "hasMore": false,
    "nextCursor": null
  }
}
```

`inboundSets` and `outboundSets` are transaction set codes, sorted. `connection` is `null` when the partner has none assigned.

Cursor pagination works as it does everywhere else: `limit` (default 50, maximum 100) and `cursor`, and when `hasMore` is `true` pass `nextCursor` back as `cursor`.

```bash
curl "https://tediware.com/platform/partners" \
  -H "Authorization: Key your-api-key-here"
```

## Get a Partner

```
GET /platform/partners/:key
```

Returns one partner with its related records embedded in full, so a single request answers everything about how that partner is set up.

```json
{
  "id": "8c2021f8-8310-4628-80f9-b578d4d68e11",
  "key": "ACME",
  "name": "Acme Foods",
  "startingInterchangeControlNumber": 1000,
  "startingGroupControlNumber": 1000,
  "autoAcknowledgeInbound": true,
  "expectFunctionalAcknowledgments": true,
  "deliveryMethod": "webhook",
  "connection": {
    "id": "a1b2c3d4-...",
    "name": "Acme SFTP",
    "kind": "sftp",
    "provisioned": true,
    "host": "sftp.acme.example",
    "port": 22,
    "username": "tediware",
    "inboundDirectory": "/out",
    "outboundDirectory": "/in"
  },
  "internalEnvelope": {
    "id": "e1f2a3b4-...",
    "name": "Our identifiers",
    "external": false,
    "interchangeExtid": "YOURID",
    "interchangeExtidQualifier": "ZZ",
    "applicationCode": "YOURID",
    "segmentSeparator": "~",
    "elementSeparator": "*",
    "componentSeparator": ">"
  },
  "externalEnvelope": {
    "id": "e5f6a7b8-...",
    "name": "Acme identifiers",
    "external": true,
    "interchangeExtid": "ACMEID",
    "interchangeExtidQualifier": "ZZ",
    "applicationCode": "ACMEID",
    "segmentSeparator": "~",
    "elementSeparator": "*",
    "componentSeparator": ">"
  },
  "inboundWebhook": {
    "id": "w1b2c3d4-...",
    "name": "Acme inbound",
    "url": "https://example.com/hooks/tediware/inbound",
    "kind": "inbound",
    "contentType": "application/json"
  },
  "outboundWebhook": null,
  "errorWebhook": null,
  "transactionSets": [
    {
      "transactionSetIdentifier": "850",
      "direction": "inbound",
      "mapping": { "id": "m1b2c3d4-...", "name": "Acme 850 inbound" },
      "implementation": null,
      "directory": "/out",
      "usageIndicator": "P"
    },
    {
      "transactionSetIdentifier": "856",
      "direction": "outbound",
      "mapping": { "id": "m5b6c7d8-...", "name": "Acme 856" },
      "implementation": { "id": "i1b2c3d4-...", "name": "Acme 856 4010" },
      "directory": "/in",
      "usageIndicator": "T"
    }
  ],
  "flows": [
    { "id": "f1b2c3d4-...", "name": "Acme Inbound", "direction": "inbound", "status": "active" },
    { "id": "f5b6c7d8-...", "name": "Acme Outbound", "direction": "outbound", "status": "active" }
  ],
  "createdAt": "2026-05-14T10:02:11.004Z",
  "updatedAt": "2026-08-29T16:41:52.118Z"
}
```

Each embedded object carries its own `id` and is `null` when nothing is assigned. The embedded shape is the one each of those resources returns from its own endpoint (see the [Configuration](/resources/api-docs/configuration) page), so code written against the embed works against the endpoint too.

`deliveryMethod` is `"webhook"` or `"poll"` and says how this partner's outcomes reach you. A `"poll"` partner has no webhooks assigned by design; read the feed instead. Flow `status` is `"active"` or `"pending"`, and only an active flow accepts traffic. The connection carries `provisioned`, and an AS2 connection also carries `as2Ready` and `as2SetupStatus`.

`transactionSets` names the document attached to each setting by reference (`{id, name}`) rather than embedding it. A mapping or an implementation is large, and the reference is what you need to confirm one is attached.

`usageIndicator` is `"P"` (production) or `"T"` (test), set per transaction setting. On an outbound set it is the ISA15 Tediware sends; `overrides.usageIndicator` on a send replaces it for one document. On an inbound set it is the value the partner is expected to send, and a document carrying the other one is processed with a `usage_indicator_mismatch` warning.

Partner keys are case-insensitive in the URL and are stored and returned uppercase. `GET /platform/partners/acme` and `GET /platform/partners/ACME` resolve the same partner.

```bash
curl "https://tediware.com/platform/partners/ACME" \
  -H "Authorization: Key your-api-key-here"
```

### Error Responses

| Status | Code         | Cause                                                                 |
|--------|--------------|-----------------------------------------------------------------------|
| 401    | unauthorized | The API key is missing or invalid                                     |
| 403    | forbidden    | The key is a sandbox key. These endpoints cover the whole organization |
| 404    | not_found    | No partner with that key exists in your organization (reason: partner) |

## The rest of the configuration

Connections, envelopes, webhooks, flows, mappings, implementations and sources each have their own list and show endpoints, described on the [Configuration](/resources/api-docs/configuration) page. Every `{id, name}` reference above resolves there.

Writes are not planned for this plane in the near term. Setup stays in the application, where it has validation, a flow builder and an audit trail behind it.
