logo Wise API

Welcome to Wise ๐Ÿš€

Introduction

Wise is an AI-powered service designed to understand, extract, and structure energy-related documents, with a strong focus on electricity bills and consumption records.

Instead of manually reading PDFs, copying values, or dealing with inconsistent formats, Wise uses artificial intelligence to convert raw energy documents into clean, structured, and reusable data that can be easily consumed by systems, teams, and automated workflows.

The Wise API gives you programmatic access to this intelligence, allowing you to integrate document processing and data extraction directly into your applications.


What Wise is built for

Wise is purpose-built to solve common problems in energy workflows, such as:

  • Reading electricity bills from different formats and providers.
  • Extracting key energy data (consumption, demand, periods, identifiers).
  • Converting unstructured documents into standardized schemas ready for analysis.
  • Keeping document histories organized, traceable, and reusable over time.

Common use cases

Wise is commonly used to:

  • Build accurate consumption histories from multiple electricity bills.
  • Prepare reliable inputs for solar, storage, and hybrid energy projects.
  • Automate document ingestion for sales, engineering, and after-sales teams.
  • Ensure teams work with consistent and validated data, not manual transcriptions.

Why use the API

By using the Wise API, you can:

  • Upload energy documents and let Wise process them automatically.
  • Retrieve structured AI-generated outputs instead of raw files.
  • Integrate Wise into your own platforms, CRMs, or internal tools.
  • Scale document processing without increasing manual effort.

Wise turns documents into data โ€” and the API is how you access that intelligence.

Interactive documentation: Visit the API Documentation at Swagger UI to explore and test endpoints.


Requirements

  • Active Wise account.
  • HTTP client (curl, Postman, Insomnia) or your own SDK.

Environments & Base URL

  • Production https://production.sunwise.ai/wise/

  • OpenAPI (Swagger) https://production.sunwise.ai/wise/api/v1/openapi.json

Check the Swagger documentation for the complete list of endpoints and available parameters.


Authentication

The API uses Bearer Token authentication via the Authorization header.

Authorization: Bearer <YOUR_API_KEY>

Example headers:

Authorization: Bearer <YOUR_API_KEY>
Content-Type: application/json
Accept: application/json

You can obtain your API key by authenticating with your Wise account credentials using the login endpoint.


Getting Started

The flow below represents what is currently available in the Wise API. For detailed behavior, request bodies, and responses, please refer to the Swagger documentation.

API workflow diagram


First Request

Replace <YOUR_API_KEY> with your actual token.

curl

curl -X GET "https://production.sunwise.ai/wise/api/v1/projects/me" \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Accept: application/json"

Usage Examples

Python (requests)

import os
import requests

BASE_URL = "https://production.sunwise.ai/wise/api/v1"
API_KEY  = os.getenv("WISE_API_KEY") or "<YOUR_API_KEY>"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Accept": "application/json",
    "Content-Type": "application/json",
}

resp = requests.get(f"{BASE_URL}/projects/me", headers=headers, timeout=30)
resp.raise_for_status()
print(resp.json())

JavaScript (fetch)

const BASE_URL = "https://production.sunwise.ai/wise/api/v1";
const API_KEY  = "<YOUR_API_KEY>";

async function main() {
  const res = await fetch(`${BASE_URL}/projects/me`, {
    method: "GET",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      Accept: "application/json",
    },
  });

  if (!res.ok) {
    throw new Error(`HTTP ${res.status}: ${await res.text()}`);
  }

  const data = await res.json();
  console.log(data);
}

main().catch(console.error);

Postman / Insomnia

  1. Open Swagger and copy the OpenAPI URL: https://production.sunwise.ai/wise/api/v1/openapi.json
  2. In Postman, go to Import โ†’ Link โ†’ and paste the OpenAPI URL.
  3. Create an environment variable called WISE_API_KEY and reference it in the headers: Authorization: Bearer {{WISE_API_KEY}}

Real-Time Updates with WebSockets ๐Ÿ”Œ

Wise provides real-time progress tracking for document processing through WebSockets. This allows your application to receive live updates as documents are being analyzed, giving your users instant feedback on the processing status.

Why use WebSockets?

When you upload a document to Wise, the AI processing happens asynchronously. Instead of polling the API repeatedly to check if the document is ready, you can open a WebSocket connection and receive instant notifications as the document moves through each processing stage.

This is especially useful for:

  • Building progress indicators in your UI.
  • Providing real-time feedback to users during uploads.
  • Detecting failures immediately without waiting for polling intervals.
  • Creating a more responsive and modern user experience.

How it works

  1. Upload documents to a project using the REST API.
  2. Open a WebSocket connection to the project's channel.
  3. Receive real-time messages as documents are processed.
  4. Close the connection when processing is complete or when you no longer need updates.

The WebSocket uses Redis Pub/Sub under the hood to broadcast messages, ensuring reliable and scalable real-time communication.


WebSocket Endpoint

ws://production.sunwise.ai/wise/ws/{project_id}

Parameters:

Parameter      Type     Description
-----------    ------   --------------------------------------------------
project_id     UUID     The unique identifier of the project to monitor.

Note: The project must exist before opening a WebSocket connection. If the project does not exist, the connection will be rejected with a 404 error.


Message Format

All messages sent through the WebSocket follow this JSON structure:

{
  "attempt": 0,
  "stage": 4,
  "document_id": "550e8400-e29b-41d4-a716-446655440000",
  "document": "electricity_bill_january.pdf",
  "status": "success"
}

Fields:

Field          Type      Description
-------------  --------  --------------------------------------------------------------------
attempt        int       The retry attempt number (starts at 0).
stage          int       The current processing stage (see table below).
document_id    string    The unique identifier of the document being processed.
document       string    The filename of the document.
status         string    Either "success" (processing normally) or "error" (processing failed).

Processing Stages

The stage field indicates where the document is in the processing pipeline:

Stage   Name                       Description
------  -------------------------  ----------------------------------------------------------
  0     UPLOADING_DOCUMENT         Document is being uploaded to storage.
  1     DOCUMENT_UPLOADED          Document has been successfully uploaded.
  2     START_DOCUMENT_FETCHING    System is retrieving the document for processing.
  3     START_TEXT_DECODING        Extracting text or images from the document.
  4     START_COMPLETION           AI model is analyzing and extracting data from the document.
  5     MERGING_PAGES              Combining results from multiple pages into a single output.
  6     START_SAVING_DOCUMENT      Saving the extracted data to the database.
  7     FINISHED                   Processing completed successfully.
 -1     FAILED                     Processing encountered an error and could not complete.

Connection Examples

Python (websockets library)

import asyncio
import json
import websockets

async def listen_to_project(project_id: str):
    uri = f"wss://production.sunwise.ai/wise/ws/{project_id}"

    async with websockets.connect(uri) as websocket:
        print("โœ… Connected to Wise WebSocket")

        async for message in websocket:
            data = json.loads(message)
            print(f"๐Ÿ“„ Document: {data['document']}")
            print(f"๐Ÿ“Š Stage: {data['stage']}")
            print(f"โœ… Status: {data['status']}")

            if data["stage"] == 7:
                print("๐ŸŽ‰ Processing complete!")
                break

            if data["stage"] == -1:
                print("โŒ Processing failed!")
                break

# Run the listener
project_id = "550e8400-e29b-41d4-a716-446655440000"
asyncio.run(listen_to_project(project_id))

Building a Progress Bar

Here's an example of how to use the stage information to build a progress bar:

const STAGES = {
  0: { name: "Uploading", progress: 10 },
  1: { name: "Uploaded", progress: 20 },
  2: { name: "Fetching", progress: 30 },
  3: { name: "Decoding", progress: 45 },
  4: { name: "Analyzing", progress: 60 },
  5: { name: "Merging", progress: 75 },
  6: { name: "Saving", progress: 90 },
  7: { name: "Complete", progress: 100 },
  "-1": { name: "Failed", progress: 0 },
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  const stage = STAGES[data.stage];

  // Update your UI
  updateProgressBar(stage.progress);
  updateStatusText(`${stage.name}: ${data.document}`);

  if (data.status === "error") {
    showErrorNotification(`Failed to process ${data.document}`);
  }
};

Best Practices

  1. Handle disconnections gracefully โ€” WebSocket connections can drop. Implement reconnection logic with exponential backoff.

  2. Close connections when done โ€” Don't leave WebSocket connections open unnecessarily. Close them when processing is complete or when the user navigates away.

  3. Validate the project exists โ€” Before opening a WebSocket, verify the project exists using the REST API to avoid unnecessary connection attempts.

  4. Use secure connections โ€” Always use wss:// (WebSocket Secure) in production environments.

  5. Handle multiple documents โ€” A project can have multiple documents. Use the document_id field to track the progress of each document individually.


Error Handling

If a document fails to process, you will receive a message with:

{
  "attempt": 0,
  "stage": -1,
  "document_id": "550e8400-e29b-41d4-a716-446655440000",
  "document": "corrupted_file.pdf",
  "status": "error"
}

Common reasons for failures include:

  • Unsupported file format โ€” The document is not a valid PDF or image.
  • Corrupted file โ€” The file is damaged and cannot be read.
  • AI processing error โ€” The AI model encountered an issue extracting data.
  • Timeout โ€” The document took too long to process.

When you receive a FAILED status, you can retrieve more details by calling the project documents endpoint or retrying the upload.


Next Steps

  1. Review the API Documentation in Swagger and identify the endpoints you need.
  2. Test endpoints using Try it out and copy the generated curl commands.
  3. Integrate the API into your application using Python, JavaScript, or your preferred language.
  4. If you have any questions about permissions, schemas, or general usage, reach out to Support.

Support