> For the complete documentation index, see [llms.txt](https://docs.crosscurve.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.crosscurve.fi/developer-documentation/integration-guide-old/direct-integration-with-rest-api/error-handling-and-recovery.md).

# Error Handling and Recovery

#### HTTP Status Codes

| Code | Meaning                    |
| ---- | -------------------------- |
| 400  | Invalid request parameters |
| 403  | Invalid or missing api-key |
| 404  | Resource not found         |
| 429  | Rate limit exceeded        |
| 500  | Internal server error      |

#### Error Response Format

All errors return a JSON object with an `error` field containing a `message`:

```json
{
  "error": {
    "message": "description of the error"
  }
}
```

For application-level errors (e.g. `PusherError`), the response also includes a `code` field:

```json
{
  "error": {
    "code": "NOT_SMART_ACCOUNT",
    "message": "Address has no deployed code — not a smart account"
  }
}
```

#### Recovery Endpoints

When a cross-chain transaction gets stuck, these endpoints help resolve the situation.

**POST /tx/create/emergency**

Build a transaction to return funds to the sender when delivery is stuck (`destination.emergency` is `true`).

| Field       | Type   | Description                                            |
| ----------- | ------ | ------------------------------------------------------ |
| `requestId` | string | The request ID from the `ComplexOpProcessed` event     |
| `signature` | string | EIP-191 signature from the original sender (see below) |

**Generating the signature:**

The server expects an EIP-191 personal sign over the keccak256 hash of the `requestId` string. The signer must be the original sender address.

```js
// Using ethers.js
import { solidityPackedKeccak256, getBytes } from "ethers";

const messageHash = solidityPackedKeccak256(["string"], [requestId]);
const signature = await signer.signMessage(getBytes(messageHash));
```

```ts
// Using viem
import { keccak256, encodePacked, toBytes } from "viem";

const messageHash = keccak256(encodePacked(["string"], [requestId]));
const signature = await walletClient.signMessage({
  message: { raw: toBytes(messageHash) },
});
```

**Full example:**

```js
// Check if emergency is available
const status = await fetch(`${API}/transaction/${requestId}`).then((r) => r.json());
if (!status.destination.emergency) {
  console.log("Emergency not yet available — wait at least 30 minutes");
}

// Generate signature
const messageHash = solidityPackedKeccak256(["string"], [requestId]);
const signature = await signer.signMessage(getBytes(messageHash));

// Build emergency transaction
const res = await fetch(`${API}/tx/create/emergency`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ requestId, signature }),
});
const emergencyTx = await res.json();

// Send on-chain
await wallet.sendTransaction({
  to: emergencyTx.to,
  data: emergencyTx.data,
  value: emergencyTx.value,
});
```

**POST /tx/create/retry**

Retry a failed delivery. Uses the same signature format as the emergency endpoint.

| Field       | Type   | Description                                        |
| ----------- | ------ | -------------------------------------------------- |
| `requestId` | string | The request ID from the `ComplexOpProcessed` event |
| `signature` | string | EIP-191 signature from the original sender         |

```js
const messageHash = solidityPackedKeccak256(["string"], [requestId]);
const signature = await signer.signMessage(getBytes(messageHash));

const res = await fetch(`${API}/tx/create/retry`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ requestId, signature }),
});
const retryTx = await res.json();
// Send retryTx on-chain
```

**POST /tx/create/resumeBr**

Resume a paused bridge relay.

```json
{
  "requestId": "0x..."
}
```

**POST /tx/create/cancelBr**

Cancel a pending bridge relay.

```json
{
  "requestId": "0x..."
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.crosscurve.fi/developer-documentation/integration-guide-old/direct-integration-with-rest-api/error-handling-and-recovery.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
