Using your API

If you haven't already configured your app, see Configuring my APP

Authentication

The API uses JWT (JSON Web Token) authentication. First, sign in to get an access token:

POST /api/auth/signin
Content-Type: application/json

{
  "TenantId": "Demo",
  "Username": "admin",
  "Password": "Admin@123"
}

This returns an access token and refresh token. Include the access token in the Authorization header for all API requests:

GET /api/Customer
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

API Examples

All content sent via the body should be in json format

# Get all product
GET /api/Product

# Get a specific product
GET /api/Product(123e4567-e89b-12d3-a456-426614174000)

# Create a new product
POST /api/Product
Content-Type: application/json
{
  "SKU": "ADJWRE",
  "SalesDescription": "Adjustable Wrench",
  "Cost": 24.65
}

# Update a product
PATCH /api/Product(123e4567-e89b-12d3-a456-426614174000)
Content-Type: application/json
{
  "Cost": 22.85
}

# Delete a product
DELETE /api/Product(123e4567-e89b-12d3-a456-426614174000)

OData Query Examples

# Filter product
GET /api/Product?$filter=Cost lt 25.00

# Sort product
GET /api/Product?$orderby=Sku

# Select specific fields
GET /api/Product?$select=Sku,SalesDescription,Cost

# Expand related entities (References or collections)
GET /api/Product?$expand=Uoms($select=Name)

# Combine queries
GET /api/Product?$filter=Cost lt 25.00&$orderby=Sku&$top=10&$select=Sku,SalesDescription

# Count
GET /api/Products?$count=true

# Aggregates
GET api/SalesOrderDetail?$apply=filter(Product/Sku eq 'EAST')/aggregate(Quantity with sum as QuantityOfEasterEggers)

A few tips:

$select

  • Entities and properties are case sensitive.
  • If select is not specified, then only the Guid property is returned.
  • All entities have a Guid and a Title property. $select=Guid,Title
  • Both virtual and persisted properties can be selected. However, returning only persisted properties is more performant.

$filter

  • You can only filter by persisted properties.
  • You can do a joined filter like this: Customer?$filter=PrimaryContact/MailingAddress/State eq 'PA'

$expand

  • Expand is used for both collections and references: SalesOrder?$expand=Details($select=Description) SalesOrder?$expand=PriceLevel($select=Name)
  • Expand and select multiple levels: Customer?$select=Id&$expand=PrimaryContact($select=FullName;$expand=MailingAddress($select=City,State))

$top and skip

  • Used for paged queries

aggregate

  • Only persisted properties can be read in aggregates.

Workflows

The Benevia platform can do multiple OData calls without saving changes between calls. This allows the client to make incremental changes and get real-time business logic modifications. For example: When entering a quantity and a product on a sales order, the business logic computes the prices and the total of the order. With workflows, the user can see these values change as he enters data into the sales order.

Lifecycle of workflow: Create workflow → Multiple OData queries → Commit

  1. Create workflow: POST /API/workflow

    {
        "message": "Workflow created successfully",
        "workflowId": "a0d77a58-b208-46ce-b7f6-ddb03b89a6af"
    }
    
  2. Do multiple OData queries such as GET, PATCH or POST with these headers:

    Workflow-Id: 1c9f2f65-7d3c-4f6b-b0d1-a2efa4a56c0d Workflow-Index: 1 Increment the index with each query

    To return updated data in your PATCH query, use $select and $expand parameters

  3. Commit workflow /api/workflow/commit with the above headers

See also

OData documentation: Getting Started · OData - the Best Way to REST

OData Aggregates: Grouping and Aggregation in OData Client - OData | Microsoft Learn