> ## Documentation Index
> Fetch the complete documentation index at: https://developer.hellgate.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Invocation

> Calling a protocol action: how Link selects a backend, runs the mapping, and returns a protocol-shaped result or error.

**Invocation** is calling a protocol action. Link validates the request, selects a matching
[backend](/products/link/concepts/backends), runs the request mapping, dispatches the provider call, maps the
response back to the [protocol's](/products/link/concepts/protocols) shape, and records an
[execution](#execution-log).

```
{METHOD} /api/invoke/{protocol}/{action}
```

`{protocol}` is the protocol's local ID and `{action}` is the action name. The call requires the `invoke:execute`
scope.

```bash theme={null}
curl -X POST https://{instance}.eu1.on-hellgate.cloud/api/invoke/specter-v1/assess \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "credential": { "type": "pan", "pan": { "value": "4111111111111111" } }, "transaction": { "amount": 4999, "currency": "USD" } }'
```

## The flow

```mermaid theme={null}
sequenceDiagram
    participant C as Caller
    participant L as Link
    participant P as Provider
    C->>L: {METHOD} /api/invoke/{protocol}/{action}
    Note over L: Validate request · resolve variant · select backend
    L->>P: Mapped, provider-native request
    P-->>L: Provider response
    Note over L: Map response · write execution log
    L-->>C: Protocol-shaped result
```

1. **Validate** the request against the action's schema.
2. **Resolve the variant** from the discriminator field, if the action is polymorphic.
3. **Select the backend** that implements the action and variant.
4. **Map and dispatch** the request to the provider.
5. **Map the response** back to the protocol shape and **log** the execution.

## Method matching

The HTTP method you invoke with must match the method the action declares in the protocol. A mismatch returns
`405 METHOD_NOT_ALLOWED` — it is not routed to a different action.

## Selecting a backend

If exactly one enabled backend implements the action and variant, Link uses it. If **several** match, Link
returns `409 CONFLICT`; disambiguate with the `backend` query parameter:

```bash theme={null}
curl -X POST "https://{instance}.eu1.on-hellgate.cloud/api/invoke/specter-v1/assess?backend=acme-risk" ...
```

## Results

A successful invocation returns the **protocol-shaped** result. Its shape is defined entirely by the protocol —
for the `specter-v1` `assess` action, that is an enum outcome:

```json theme={null}
{ "type": "enum", "value": "ALLOW", "backend_reference": "dec-xyz" }
```

Two response headers accompany every result:

* **`x-link-execution`** — the execution ID; use it to fetch the [audit entry](#execution-log).
* **`server-timing`** — total and external-call timing, in milliseconds.

### Mapping errors

When the provider call completes but mapping cannot produce a valid result, Link returns a protocol **error**
result rather than failing silently. The `source` field tells you where it originated:

```json theme={null}
{ "type": "error", "source": "mapping", "code": "MISSING_REQUIRED_FIELD", "message": "..." }
```

`source` tells you where the error originated: `backend` (the provider returned an error you mapped through),
`mapping` (a `required` leaf could not resolve), `transport` (the provider was unreachable or timed out),
`encryption` (message-level encryption failed), or `mock` (a configured mock returned an error). Transport and
encryption failures carry HTTP `502`; the rest use the status from the response mapping.

## Error codes

| Status | Code                    | Cause                                                                      |
| ------ | ----------------------- | -------------------------------------------------------------------------- |
| `401`  | `UNAUTHORIZED`          | Missing, expired, or malformed bearer token                                |
| `403`  | `FORBIDDEN`             | Token lacks the `invoke:execute` scope                                     |
| `404`  | `action_not_supported`  | No enabled backend implements this action                                  |
| `404`  | `variant_not_supported` | The discriminator selected a variant no backend implements                 |
| `405`  | `METHOD_NOT_ALLOWED`    | The HTTP method does not match the action's declared method                |
| `409`  | `ambiguous_backend`     | Multiple backends match — pass `?backend=<id>`                             |
| `422`  | `VALIDATION_ERROR`      | The request failed schema validation — see `validation_errors` in the body |
| `422`  | `BACKEND_DISABLED`      | The only matching backend is disabled                                      |

## Execution log

Every invocation — success or failure — is logged asynchronously. Fetch an entry by ID with the
`admin:executions:read` scope:

```bash theme={null}
curl -H "Authorization: Bearer $TOKEN" \
  https://{instance}.eu1.on-hellgate.cloud/api/admin/executions/<execution-id>
```

The entry contains the mapped protocol result, the raw provider response, timing, the backend that handled the
call, and any error detail — so you can verify a round trip without provider-side tooling.

## Next steps

<CardGroup cols={2}>
  <Card title="Backends" icon="plug" href="/products/link/concepts/backends">
    Configure the mapping that shapes each request and response.
  </Card>

  <Card title="Quickstart" icon="rocket" href="/products/link/quickstart">
    Run the full flow end to end.
  </Card>
</CardGroup>
