Workflow Management

Workflow Management

This section covers all APIs related to workflow creation, configuration, and management.

Postman Collection

Workflow Schema

Before diving into the APIs, here's the common schema for a workflow:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "description": "string",
  "fields": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440001",
      "name": "string" // Only alphanumeric and underscore allowed. Must be unique within workflow.
    }
  ],
  "table_headers": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440002",
      "name": "string" // Only alphanumeric and underscore allowed. Must be unique within workflow.
    }
  ],
  "settings": {
    "table_capture": boolean // enable capturing of tables on documents
  },
  "created_at": "string"
}

Workflow Limits

The following limits apply to workflow management:

Account Limits

  • Maximum number of workflows per account: 20
  • Exceeding this limit will result in a 400 (Bad Request) response

Field Limits

  • Maximum number of fields per workflow: 30
  • Exceeding this limit will result in a 400 (Bad Request) response
  • Applies to both instant learning and pre-trained workflows
  • Includes all fields across all document types in the workflow

Table Header Limits

  • Maximum number of table headers per workflow: 20
  • Exceeding this limit will result in a 400 (Bad Request) response
  • Applies to both instant learning and pre-trained workflows
  • Includes all table headers across all document types in the workflow

List Workflows

Postman

Retrieves a list of all workflows in your account.

Endpoint: GET /api/v4/workflows

Overview

  • Lists all workflows in your account
  • Supports pagination for large numbers of workflows
  • Returns basic workflow information including ID, description, and creation date
  • Includes field and table configurations for each workflow

Response:

{
  "workflows": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "description": "Extract data from invoices",
      "fields": [
        {
          "id": "550e8400-e29b-41d4-a716-446655440001",
          "name": "invoice_number"
        }
      ],
      "table_headers": [
        {
          "id": "550e8400-e29b-41d4-a716-446655440002",
          "name": "description"
        }
      ],
      "settings": {
        "table_capture": true
      },
      "created_at": "2024-02-20T10:00:00Z"
    }
  ]
}

Example:

import requests
from requests.auth import HTTPBasicAuth

API_KEY = 'YOUR_API_KEY'
url = "https://app.nanonets.com/api/v4/workflows"

response = requests.get(
    url,
    auth=HTTPBasicAuth(API_KEY, '')
)
print(response.json())
curl -X GET \
  -u "YOUR_API_KEY:" \
  https://app.nanonets.com/api/v4/workflows
const axios = require('axios');

const API_KEY = 'YOUR_API_KEY';
const url = 'https://app.nanonets.com/api/v4/workflows';

axios.get(url, {
  auth: {
    username: API_KEY,
    password: ''
  }
})
.then(response => {
  console.log(response.data);
})
.catch(error => {
  console.error(error);
});
package main

import (
    "fmt"
    "net/http"
    "encoding/base64"
)

func main() {
    API_KEY := "YOUR_API_KEY"
    url := "https://app.nanonets.com/api/v4/workflows"

    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        fmt.Println(err)
        return
    }

    auth := base64.StdEncoding.EncodeToString([]byte(API_KEY + ":"))
    req.Header.Add("Authorization", "Basic "+auth)

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer resp.Body.Close()
}

Get Workflow by ID

Postman

Retrieve detailed information about a specific workflow.

GET /api/v4/workflows/{workflow_id}

Overview

  • Retrieves complete workflow configuration
  • Includes all fields, table headers, and settings
  • Useful for verifying workflow configuration
  • Returns the most up-to-date workflow state

Response

Returns the complete workflow schema including all fields and table headers.

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "description": "Process invoices and extract key information",
  "fields": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440001",
      "name": "Invoice Number"
    },
    {
      "id": "550e8400-e29b-41d4-a716-446655440002",
      "name": "Total Amount"
    }
  ],
  "table_headers": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440003",
      "name": "Item Description"
    },
    {
      "id": "550e8400-e29b-41d4-a716-446655440004",
      "name": "Quantity"
    }
  ],
  "settings": {
    "table_capture": true
  },
  "created_at": "2024-03-14T12:00:00Z"
}

Example

import requests
from requests.auth import HTTPBasicAuth

API_KEY = 'YOUR_API_KEY'
WORKFLOW_ID = '550e8400-e29b-41d4-a716-446655440000'
url = f"https://app.nanonets.com/api/v4/workflows/{WORKFLOW_ID}"

response = requests.get(
    url,
    auth=HTTPBasicAuth(API_KEY, '')
)
print(response.json())
curl -X GET \
  -u "YOUR_API_KEY:" \
  https://app.nanonets.com/api/v4/workflows/550e8400-e29b-41d4-a716-446655440000
const axios = require('axios');

const API_KEY = 'YOUR_API_KEY';
const WORKFLOW_ID = '550e8400-e29b-41d4-a716-446655440000';
const url = `https://app.nanonets.com/api/v4/workflows/${WORKFLOW_ID}`;

axios.get(url, {
  auth: {
    username: API_KEY,
    password: ''
  }
})
.then(response => {
  console.log(response.data);
})
.catch(error => {
  console.error(error);
});
package main

import (
    "fmt"
    "net/http"
    "encoding/base64"
)

func main() {
    API_KEY := "YOUR_API_KEY"
    WORKFLOW_ID := "550e8400-e29b-41d4-a716-446655440000"
    url := fmt.Sprintf("https://app.nanonets.com/api/v4/workflows/%s", WORKFLOW_ID)

    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        fmt.Println(err)
        return
    }

    auth := base64.StdEncoding.EncodeToString([]byte(API_KEY + ":"))
    req.Header.Add("Authorization", "Basic "+auth)

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer resp.Body.Close()
}

Get Available Workflow Types

Postman

Get a list of all available workflow types that can be used when creating a workflow.

GET /api/v4/workflow_types

Response

{
  "workflow_types": [
    {
      "id": "",
      "name": "Instant Learning",
      "description": "Train model instantly with a few examples (default workflow type). Requires field configuration."
    },
    {
      "id": "invoice",
      "name": "Invoice",
      "description": "Extract data from invoices. Comes with pre-configured fields."
    },
    {
      "id": "receipt",
      "name": "Receipt",
      "description": "Extract data from receipts. Comes with pre-configured fields."
    },
    {
      "id": "tables",
      "name": "Tables",
      "description": "Extract tabular data from documents. Comes with pre-configured fields."
    },
    {
      "id": "purchase_order",
      "name": "Purchase Order",
      "description": "Extract data from purchase orders. Comes with pre-configured fields."
    },
    {
      "id": "passport",
      "name": "Passport",
      "description": "Extract data from passports. Comes with pre-configured fields."
    },
    {
      "id": "bill_of_lading",
      "name": "Bill of Lading",
      "description": "Extract data from bills of lading. Comes with pre-configured fields."
    }
  ]
}

Workflow Types Overview

The API provides several workflow types to choose from:

  1. Instant Learning (Default)

    • Use empty string "" as the workflow type
    • Requires manual field configuration
    • Best for any generic or custom document types
  2. Pre-trained Workflows

    • Include "invoice", "receipt", "tables", "purchase_order", "passport", and "bill_of_lading"
    • Come with pre-configured fields optimized for each document type
    • No manual field configuration required
    • Fields can be modified or deleted after creation
    • Best for standard document types with known layouts

Example

import requests
from requests.auth import HTTPBasicAuth

API_KEY = 'YOUR_API_KEY'
url = "https://app.nanonets.com/api/v4/workflow_types"

response = requests.get(
    url,
    auth=HTTPBasicAuth(API_KEY, '')
)
workflow_types = response.json()['workflow_types']

# Print available workflow types
for workflow in workflow_types:
    print(f"ID: {workflow['id']}")
    print(f"Name: {workflow['name']}")
    print(f"Description: {workflow['description']}")
    print("---")
curl -X GET \
  -u "YOUR_API_KEY:" \
  https://app.nanonets.com/api/v4/workflow_types
const axios = require('axios');

const API_KEY = 'YOUR_API_KEY';
const url = 'https://app.nanonets.com/api/v4/workflow_types';

axios.get(url, {
  auth: {
    username: API_KEY,
    password: ''
  }
})
.then(response => {
  const workflowTypes = response.data.workflow_types;
  workflowTypes.forEach(workflow => {
    console.log(`ID: ${workflow.id}`);
    console.log(`Name: ${workflow.name}`);
    console.log(`Description: ${workflow.description}`);
    console.log('---');
  });
})
.catch(error => {
  console.error(error);
});
package main

import (
    "fmt"
    "net/http"
    "encoding/base64"
    "encoding/json"
)

type WorkflowType struct {
    ID          string `json:"id"`
    Name        string `json:"name"`
    Description string `json:"description"`
}

type WorkflowTypesResponse struct {
    WorkflowTypes []WorkflowType `json:"workflow_types"`
}

func main() {
    API_KEY := "YOUR_API_KEY"
    url := "https://app.nanonets.com/api/v4/workflow_types"

    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        fmt.Println(err)
        return
    }

    auth := base64.StdEncoding.EncodeToString([]byte(API_KEY + ":"))
    req.Header.Add("Authorization", "Basic "+auth)

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer resp.Body.Close()

    var result WorkflowTypesResponse
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        fmt.Println(err)
        return
    }

    for _, workflow := range result.WorkflowTypes {
        fmt.Printf("ID: %s\n", workflow.ID)
        fmt.Printf("Name: %s\n", workflow.Name)
        fmt.Printf("Description: %s\n", workflow.Description)
        fmt.Println("---")
    }
}

Create Workflow

Postman

Create a new workflow with a specific workflow type or instant learning workflow.

POST /api/v4/workflows

Overview

  • Creates a new workflow with specified type
  • For instant learning workflows, field configuration is required after creation
  • For pre-trained workflows, fields are pre-configured but can be modified
  • Returns the created workflow with its ID and initial configuration

Request

{
  "description": "Extract data from invoices",
  "workflow_type": "invoice" // Options: "invoice", "receipt", "tables", "purchase_order", "passport", "bill_of_lading". Use empty string "" for instant learning workflow (default).
}

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "description": "Extract data from invoices",
  "fields": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440001",
      "name": "invoice_number"  // Pre-configured field names follow alphanumeric and underscore rule
    },
    {
      "id": "550e8400-e29b-41d4-a716-446655440002",
      "name": "total_amount"
    }
  ],
  "table_headers": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440003",
      "name": "item_description"  // Pre-configured table header names follow alphanumeric and underscore rule
    },
    {
      "id": "550e8400-e29b-41d4-a716-446655440004",
      "name": "quantity"
    }
  ],
  "settings": {
    "table_capture": true
  },
  "created_at": "2024-03-14T12:00:00Z"
}

Example

import requests
from requests.auth import HTTPBasicAuth

API_KEY = 'YOUR_API_KEY'
url = "https://app.nanonets.com/api/v4/workflows"

# Create instant learning workflow (default)
instant_payload = {
    "description": "Extract data from custom documents",
    "workflow_type": ""  # Empty string for instant learning workflow
}

response = requests.post(
    url,
    json=instant_payload,
    auth=HTTPBasicAuth(API_KEY, '')
)
print(response.json())

# Create workflow with invoice type
invoice_payload = {
    "description": "Extract data from invoices",
    "workflow_type": "invoice"
}

response = requests.post(
    url,
    json=invoice_payload,
    auth=HTTPBasicAuth(API_KEY, '')
)
print(response.json())
# Create instant learning workflow
curl -X POST \
  -u "YOUR_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Extract data from custom documents",
    "workflow_type": ""
  }' \
  https://app.nanonets.com/api/v4/workflows

# Create invoice workflow
curl -X POST \
  -u "YOUR_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Extract data from invoices",
    "workflow_type": "invoice"
  }' \
  https://app.nanonets.com/api/v4/workflows
const axios = require('axios');

const API_KEY = 'YOUR_API_KEY';
const url = 'https://app.nanonets.com/api/v4/workflows';

// Create instant learning workflow
const instantPayload = {
  description: "Extract data from custom documents",
  workflow_type: ""  // Empty string for instant learning workflow
};

axios.post(url, instantPayload, {
  auth: {
    username: API_KEY,
    password: ''
  }
})
.then(response => {
  console.log(response.data);
})
.catch(error => {
  console.error(error);
});

// Create invoice workflow
const invoicePayload = {
  description: "Extract data from invoices",
  workflow_type: "invoice"
};

axios.post(url, invoicePayload, {
  auth: {
    username: API_KEY,
    password: ''
  }
})
.then(response => {
  console.log(response.data);
})
.catch(error => {
  console.error(error);
});
package main

import (
    "fmt"
    "net/http"
    "encoding/base64"
    "encoding/json"
    "bytes"
)

type WorkflowPayload struct {
    Description string `json:"description"`
    WorkflowType string `json:"workflow_type"`
}

func createWorkflow(payload WorkflowPayload) error {
    API_KEY := "YOUR_API_KEY"
    url := "https://app.nanonets.com/api/v4/workflows"

    jsonData, err := json.Marshal(payload)
    if err != nil {
        return err
    }

    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    if err != nil {
        return err
    }

    auth := base64.StdEncoding.EncodeToString([]byte(API_KEY + ":"))
    req.Header.Add("Authorization", "Basic "+auth)
    req.Header.Add("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    var result map[string]interface{}
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        return err
    }

    fmt.Printf("%+v\n", result)
    return nil
}

func main() {
    // Create instant learning workflow
    instantPayload := WorkflowPayload{
        Description: "Extract data from custom documents",
        WorkflowType: "",
    }

    if err := createWorkflow(instantPayload); err != nil {
        fmt.Println("Error creating workflow:", err)
        return
    }

    // Create invoice workflow
    invoicePayload := WorkflowPayload{
        Description: "Extract data from invoices",
        WorkflowType: "invoice",
    }

    if err := createWorkflow(invoicePayload); err != nil {
        fmt.Println("Error creating workflow:", err)
        return
    }
}

Set Fields and Table Headers

Postman

Configure which fields and table headers to extract from documents.

PUT /api/v4/workflows/{workflow_id}/fields

Overview

  • Configures fields and table headers for document extraction
  • Required for instant learning workflows
  • Optional for pre-trained workflows (can modify existing fields)
  • Replaces all existing fields and table headers
  • Each field and table header gets a unique ID for future updates
  • Field and table header names must:
    • Contain only alphanumeric characters and underscores
    • Be unique within the workflow
    • Not contain spaces or special characters

Request

{
  "fields": [
    {
      "name": "invoice_number"  // Valid: alphanumeric and underscore only
    },
    {
      "name": "total_amount"    // Valid: alphanumeric and underscore only
    },
    {
      "name": "invoice_date"    // Valid: alphanumeric and underscore only
    }
  ],
  "table_headers": [
    {
      "name": "item_description"  // Valid: alphanumeric and underscore only
    },
    {
      "name": "quantity"          // Valid: alphanumeric and underscore only
    },
    {
      "name": "unit_price"        // Valid: alphanumeric and underscore only
    },
    {
      "name": "total"             // Valid: alphanumeric and underscore only
    }
  ]
}

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "fields": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440001",
      "name": "invoice_number"
    },
    {
      "id": "550e8400-e29b-41d4-a716-446655440002",
      "name": "total_amount"
    },
    {
      "id": "550e8400-e29b-41d4-a716-446655440003",
      "name": "invoice_date"
    }
  ],
  "table_headers": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440004",
      "name": "item_description"
    },
    {
      "id": "550e8400-e29b-41d4-a716-446655440005",
      "name": "quantity"
    },
    {
      "id": "550e8400-e29b-41d4-a716-446655440006",
      "name": "unit_price"
    },
    {
      "id": "550e8400-e29b-41d4-a716-446655440007",
      "name": "total"
    }
  ],
  "created_at": "2024-03-14T12:30:00Z"
}

Example

import requests
from requests.auth import HTTPBasicAuth

API_KEY = 'YOUR_API_KEY'
WORKFLOW_ID = '550e8400-e29b-41d4-a716-446655440000'
url = f"https://app.nanonets.com/api/v4/workflows/{WORKFLOW_ID}/fields"

payload = {
    "fields": [
        {
            "name": "invoice_number"
        },
        {
            "name": "total_amount"
        },
        {
            "name": "invoice_date"
        }
    ],
    "table_headers": [
        {
            "name": "item_description"
        },
        {
            "name": "quantity"
        },
        {
            "name": "unit_price"
        },
        {
            "name": "total"
        }
    ]
}

response = requests.put(
    url,
    json=payload,
    auth=HTTPBasicAuth(API_KEY, '')
)
print(response.json())
curl -X PUT \
  -u "YOUR_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": [
      {
        "name": "invoice_number"
      },
      {
        "name": "total_amount"
      },
      {
        "name": "invoice_date"
      }
    ],
    "table_headers": [
      {
        "name": "item_description"
      },
      {
        "name": "quantity"
      },
      {
        "name": "unit_price"
      },
      {
        "name": "total"
      }
    ]
  }' \
  https://app.nanonets.com/api/v4/workflows/550e8400-e29b-41d4-a716-446655440000/fields
const axios = require('axios');

const API_KEY = 'YOUR_API_KEY';
const WORKFLOW_ID = '550e8400-e29b-41d4-a716-446655440000';
const url = `https://app.nanonets.com/api/v4/workflows/${WORKFLOW_ID}/fields`;

const payload = {
  fields: [
    {
      name: "invoice_number"
    },
    {
      name: "total_amount"
    },
    {
      name: "invoice_date"
    }
  ],
  table_headers: [
    {
      name: "item_description"
    },
    {
      name: "quantity"
    },
    {
      name: "unit_price"
    },
    {
      name: "total"
    }
  ]
};

axios.put(url, payload, {
  auth: {
    username: API_KEY,
    password: ''
  }
})
.then(response => {
  console.log(response.data);
})
.catch(error => {
  console.error(error);
});
package main

import (
    "fmt"
    "net/http"
    "encoding/base64"
    "encoding/json"
    "bytes"
)

type Field struct {
    Name string `json:"name"`
}

type TableHeader struct {
    Name string `json:"name"`
}

type FieldsPayload struct {
    Fields       []Field       `json:"fields"`
    TableHeaders []TableHeader `json:"table_headers"`
}

func setFieldsAndHeaders(workflowId string, payload FieldsPayload) error {
    API_KEY := "YOUR_API_KEY"
    url := fmt.Sprintf("https://app.nanonets.com/api/v4/workflows/%s/fields", workflowId)

    jsonData, err := json.Marshal(payload)
    if err != nil {
        return err
    }

    req, err := http.NewRequest("PUT", url, bytes.NewBuffer(jsonData))
    if err != nil {
        return err
    }

    auth := base64.StdEncoding.EncodeToString([]byte(API_KEY + ":"))
    req.Header.Add("Authorization", "Basic "+auth)
    req.Header.Add("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    var result map[string]interface{}
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        return err
    }

    fmt.Printf("%+v\n", result)
    return nil
}

func main() {
    WORKFLOW_ID := "550e8400-e29b-41d4-a716-446655440000"
    
    payload := FieldsPayload{
        Fields: []Field{
            {Name: "invoice_number"},
            {Name: "total_amount"},
            {Name: "invoice_date"},
        },
        TableHeaders: []TableHeader{
            {Name: "item_description"},
            {Name: "quantity"},
            {Name: "unit_price"},
            {Name: "total"},
        },
    }

    if err := setFieldsAndHeaders(WORKFLOW_ID, payload); err != nil {
        fmt.Println("Error setting fields and headers:", err)
        return
    }

    fmt.Println("Fields and headers set successfully")
}

Update Field or Table Header

Postman

Modify an existing field or table header configuration.

PATCH /api/v4/workflows/{workflow_id}/fields/{field_id}

Overview

  • Updates a single field or table header
  • Preserves other fields and configurations
  • Useful for making targeted changes
  • Can be used to rename or modify field properties
  • New names must follow the same rules:
    • Only alphanumeric characters and underscores allowed
    • Must be unique within the workflow
    • No spaces or special characters

Request

{
  "name": "invoice_number"  // Valid: alphanumeric and underscore only
}

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440001",
  "name": "invoice_number"
}

Example

import requests
from requests.auth import HTTPBasicAuth

API_KEY = 'YOUR_API_KEY'
WORKFLOW_ID = '550e8400-e29b-41d4-a716-446655440000'
FIELD_ID = '550e8400-e29b-41d4-a716-446655440001'
url = f"https://app.nanonets.com/api/v4/workflows/{WORKFLOW_ID}/fields/{FIELD_ID}"

payload = {
    "name": "invoice_number"
}

response = requests.patch(
    url,
    json=payload,
    auth=HTTPBasicAuth(API_KEY, '')
)
print(response.json())
curl -X PATCH \
  -u "YOUR_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "invoice_number"
  }' \
  https://app.nanonets.com/api/v4/workflows/550e8400-e29b-41d4-a716-446655440000/fields/550e8400-e29b-41d4-a716-446655440001
const axios = require('axios');

const API_KEY = 'YOUR_API_KEY';
const WORKFLOW_ID = '550e8400-e29b-41d4-a716-446655440000';
const FIELD_ID = '550e8400-e29b-41d4-a716-446655440001';
const url = `https://app.nanonets.com/api/v4/workflows/${WORKFLOW_ID}/fields/${FIELD_ID}`;

const payload = {
  name: "invoice_number"
};

axios.patch(url, payload, {
  auth: {
    username: API_KEY,
    password: ''
  }
})
.then(response => {
  console.log(response.data);
})
.catch(error => {
  console.error(error);
});
package main

import (
    "fmt"
    "net/http"
    "encoding/base64"
    "encoding/json"
    "bytes"
)

type FieldUpdate struct {
    Name string `json:"name"`
}

func updateField(workflowId, fieldId string, payload FieldUpdate) error {
    API_KEY := "YOUR_API_KEY"
    url := fmt.Sprintf("https://app.nanonets.com/api/v4/workflows/%s/fields/%s", workflowId, fieldId)

    jsonData, err := json.Marshal(payload)
    if err != nil {
        return err
    }

    req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(jsonData))
    if err != nil {
        return err
    }

    auth := base64.StdEncoding.EncodeToString([]byte(API_KEY + ":"))
    req.Header.Add("Authorization", "Basic "+auth)
    req.Header.Add("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    var result map[string]interface{}
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        return err
    }

    fmt.Printf("%+v\n", result)
    return nil
}

func main() {
    WORKFLOW_ID := "550e8400-e29b-41d4-a716-446655440000"
    FIELD_ID := "550e8400-e29b-41d4-a716-446655440001"
    
    payload := FieldUpdate{
        Name: "invoice_number",
    }

    if err := updateField(WORKFLOW_ID, FIELD_ID, payload); err != nil {
        fmt.Println("Error updating field:", err)
        return
    }

    fmt.Println("Field updated successfully")
}

Delete Field or Table Header

Postman

Remove a field or table header from the workflow.

DELETE /api/v4/workflows/{workflow_id}/fields/{field_id}

Overview

  • Removes a specific field or table header
  • Cannot be undone
  • Other fields and configurations remain unchanged
  • Useful for removing unused or redundant fields

Response

{
  "message": "Field deleted successfully"
}

Update Workflow Metadata

Postman

Modify workflow description.

PATCH /api/v4/workflows/{workflow_id}

Overview

  • Updates basic workflow information
  • Does not affect field configurations or settings
  • Useful for organizing and documenting workflows
  • Can be updated at any time

Request

{
  "description": "Updated workflow description"
}

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "description": "Updated workflow description",
  "created_at": "2024-03-14T13:00:00Z"
}

Update Workflow Settings

Postman

Configure table capture settings.

PATCH /api/v4/workflows/{workflow_id}/settings

Overview

  • Configures how documents are processed
  • Enables/disables table capture
  • Can be updated at any time
  • Changes take effect immediately for new documents

Request

{
  "table_capture": true  // Enable or disable table capture
}

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "type": "invoice",
  "settings": {
    "table_capture": true
  }
}

Common Use Cases

Creating an Instant Learning Workflow

import requests
from requests.auth import HTTPBasicAuth

API_KEY = 'YOUR_API_KEY'
url = "https://app.nanonets.com/api/v4/workflows"

# Create workflow
workflow_payload = {
    "description": "Extract data from custom documents",
    "workflow_type": ""  # Instant learning workflow requires field configuration
}

workflow_response = requests.post(
    url,
    json=workflow_payload,
    auth=HTTPBasicAuth(API_KEY, '')
)
workflow_id = workflow_response.json()['id']

# Required field configuration for instant learning
fields_payload = {
    "fields": [
        {
            "name": "field_1"  # Valid: alphanumeric and underscore only
        },
        {
            "name": "field_2"  # Valid: alphanumeric and underscore only
        }
    ]
}

requests.put(
    f"{url}/{workflow_id}/fields",
    json=fields_payload,
    auth=HTTPBasicAuth(API_KEY, '')
)
# Create workflow
curl -X POST \
  -u "YOUR_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Extract data from custom documents",
    "workflow_type": ""
  }' \
  https://app.nanonets.com/api/v4/workflows

# Configure fields
curl -X PUT \
  -u "YOUR_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": [
      {
        "name": "field_1"  # Valid: alphanumeric and underscore only
      },
      {
        "name": "field_2"  # Valid: alphanumeric and underscore only
      }
    ]
  }' \
  https://app.nanonets.com/api/v4/workflows/WORKFLOW_ID/fields
const axios = require('axios');

const API_KEY = 'YOUR_API_KEY';
const url = 'https://app.nanonets.com/api/v4/workflows';

// Create instant learning workflow
const instantPayload = {
  description: "Extract data from custom documents",
  workflow_type: ""  // Instant learning workflow requires field configuration
};

axios.post(url, instantPayload, {
  auth: {
    username: API_KEY,
    password: ''
  }
})
.then(response => {
  const workflowId = response.data.id;
  
  // Configure fields
  const fieldsPayload = {
    fields: [
      {
        name: "field_1"  // Valid: alphanumeric and underscore only
      },
      {
        name: "field_2"  // Valid: alphanumeric and underscore only
      }
    ]
  };

  return axios.put(
    `${url}/${workflowId}/fields`,
    fieldsPayload,
    {
      auth: {
        username: API_KEY,
        password: ''
      }
    }
  );
})
.then(response => {
  console.log('Fields configured successfully:', response.data);
})
.catch(error => {
  console.error('Error:', error);
});
package main

import (
    "fmt"
    "net/http"
    "encoding/base64"
    "encoding/json"
    "bytes"
)

type WorkflowPayload struct {
    Description string `json:"description"`
    WorkflowType string `json:"workflow_type"`
}

func createWorkflow(payload WorkflowPayload) error {
    API_KEY := "YOUR_API_KEY"
    url := "https://app.nanonets.com/api/v4/workflows"

    jsonData, err := json.Marshal(payload)
    if err != nil {
        return err
    }

    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    if err != nil {
        return err
    }

    auth := base64.StdEncoding.EncodeToString([]byte(API_KEY + ":"))
    req.Header.Add("Authorization", "Basic "+auth)
    req.Header.Add("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    var result map[string]interface{}
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        return err
    }

    fmt.Printf("%+v\n", result)
    return nil
}

func main() {
    // Create instant learning workflow
    instantPayload := WorkflowPayload{
        Description: "Extract data from custom documents",
        WorkflowType: "",
    }

    if err := createWorkflow(instantPayload); err != nil {
        fmt.Println("Error creating workflow:", err)
        return
    }

    // Create invoice workflow
    invoicePayload := WorkflowPayload{
        Description: "Extract data from invoices",
        WorkflowType: "invoice",
    }

    if err := createWorkflow(invoicePayload); err != nil {
        fmt.Println("Error creating workflow:", err)
        return
    }
}

Error Handling

All workflow management APIs return standard HTTP status codes:

  • 200 OK: Request successful
  • 201 Created: Resource created successfully
  • 400 Bad Request: Invalid request parameters
  • 401 Unauthorized: Invalid or missing API key
  • 404 Not Found: Workflow or field not found
  • 409 Conflict: Resource already exists
  • 500 Internal Server Error: Server-side error

Common Error Scenarios

  1. Invalid Field or Table Header Names

    • Occurs when using characters other than alphanumeric and underscore
    • Ensure names only contain letters, numbers, and underscores
    • Example: "invoice-number" is invalid, use "invoice_number" instead
  2. Duplicate Field Names

    • Occurs when creating fields with duplicate names within a workflow
    • Ensure unique field names within a workflow
    • Example: Cannot have two fields named "total_amount"
  3. Duplicate Table Header Names

    • Occurs when creating table headers with duplicate names within a workflow
    • Ensure unique table header names within a workflow
    • Example: Cannot have two table headers named "quantity"
  4. Missing Field Configuration

    • Occurs when trying to use an instant learning workflow without field configuration
    • Always configure fields after creating an instant learning workflow

For detailed error handling, refer to the Error Handling Guide.

Best Practices

  1. Field Configuration

    • Use clear, descriptive field names (e.g., "invoice_number" instead of "number")
    • Ensure field names are unique within a workflow
  2. Table Configuration

    • Keep table headers concise
    • Consider table structure in your documents
  3. Settings Management

    • Choose sync/async based on your use case
    • Enable table capture for table extraction

For more best practices, refer to the Best Practices Guide.