NegoBill API v1

Create sales, contacts and payments in a NegoBill business from your own software. This page and https://api.negobill.com/openapi.json (OpenAPI 3.1) are generated from the same source and describe exactly what the server does.

Overview

Quickstart

  1. In NegoBill (web), open Settings → API Access → New key. Tick the scopes you need, copy the Key Secret — it is shown once.
  2. Run:
    curl -u "nbk_live_Ab3dEf6hIj9kLm2n:nbs_9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a" \
      https://api.negobill.com/v1/me
    A 200 with "status": true and your business name means the setup is right. Any other answer: see the error table.
  3. Create the customer (POST /contacts), then the sale (POST /sales) with its id, then record the payment (POST /sales/{id}/payments).

Authentication

HTTP Basic: the Key ID as the username and the Key Secret as the password, on every call.

Authorization: Basic base64("nbk_live_Ab3dEf6hIj9kLm2n:nbs_9f8e7d6c…")

A key carries scopes; each endpoint below names the one it needs. A key without it gets 403 NB-B-API-1004. Scopes: contacts:read (Look up customers and suppliers.), contacts:write (Add customers your software already knows.), products:read (Look up products, prices and stock left.), sales:read (Read a sale and what is still due on it.), sales:write (Make sales — NegoBill computes GST, totals and stock.), payments:read (Read the receipts recorded against a sale.), payments:write (Record money received against a sale.).

Keys do not expire. The owner can revoke a key (it stops at once), regenerate its secret (the old secret keeps working for the overlap the owner chose, 24 hours by default), and restrict it to an IP allowlist (403 NB-B-API-1008 from anywhere else).

Response envelope

Every JSON answer has this shape. correlationId is also returned as the x-correlation-id header — quote it when asking for help.

{ "status": true,  "statusCode": 200, "correlationId": "2f6c1e0a9b3d4", "results": { … } }
{ "status": false, "statusCode": 400, "correlationId": "2f6c1e0a9b3d4", "code": "NB-B-API-1000", "message": "Validation failed. See details.", "details": [ { "path": "lines.0.quantity", "message": "…" } ] }

Idempotency and retries

Send Idempotency-Key: <a unique string, ≤80 characters> on any POST. The same key with the same body returns the stored answer (with the header Idempotent-Replayed: true); the same key with a different body is refused with 409 NB-B-API-1006; a key whose first call is still running answers 409 too — wait a second and retry. Keys are remembered for 7 days. A failed first call (4xx/5xx) does not consume the key. Independently of this header, POST /contacts, POST /sales and POST /sales/{id}/payments return the existing record when your reference already exists, so a retry never duplicates a customer, a bill or a receipt.

Rate limits

120 requests a minute per key. Every answer carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix seconds). Past the limit: 429 NB-B-API-1005 with Retry-After (seconds) — wait that long, then retry. Lookups return at most 50 rows and are for looking things up, not for copying a catalogue: keep your own copy of your products and customers. Sales made through the API count in the plan's monthly sale quota (403 NB-B-PLN-1006 when it is reached).

Endpoints

GET https://api.negobill.com/v1/me

Who am I. Confirms the credentials and tells you which business, store and billing profile this key acts for. The quickstart call.

Scope: contacts:read · Header: Authorization: Basic <base64(keyId:keySecret)>

Response 200

The envelope (below) with results of:

FieldTypeRequiredNotes
businessobjectno
  idstring, 24 hex charactersno
  namestringno
storeobjectnoThe store every sale made with this key belongs to.
  idstring, 24 hex charactersno
  namestringno
  timezonestringnoIANA zone, e.g. Asia/Kolkata.
billingProfileobjectno
  idstring, 24 hex charactersno
  legalNamestring | nullno
  gstNumberstring | nullnoWhen null the business issues BILLs only; INVOICE is refused.
planobjectno
  codestringnoSTARTER, STANDARD or PRO.
  labelstringno
keyobjectno
  keyIdstringno
  labelstringno
  scopesstring[]no
  environmentstringnoLIVE or TEST.

Example response

{
  "status": true,
  "statusCode": 200,
  "correlationId": "2f6c1e0a9b3d4",
  "results": {
    "business": {
      "id": "66f1a2b3c4d5e6f7a8b9c0a0",
      "name": "Kiran Super Mart"
    },
    "store": {
      "id": "66f1a2b3c4d5e6f7a8b9c0a1",
      "name": "Main store",
      "timezone": "Asia/Kolkata"
    },
    "billingProfile": {
      "id": "66f1a2b3c4d5e6f7a8b9c0a2",
      "legalName": "Kiran Super Mart",
      "gstNumber": "33AAAAA0000A1Z5"
    },
    "plan": {
      "code": "BUSINESS",
      "label": "Business"
    },
    "key": {
      "keyId": "nbk_live_Ab3dEf6hIj9kLm2n",
      "label": "Shopify connector",
      "scopes": [
        "contacts:read",
        "sales:write"
      ],
      "environment": "LIVE"
    }
  }
}

POST https://api.negobill.com/v1/contacts

Find or create a contact. Looks for an existing contact by reference, then by gstNumber, then by phone; a match is returned with created:false (and takes your reference if it had none). Otherwise the contact is created and returned with created:true. Phone and GST number are unique within a business, which is why matching comes first.

Scope: contacts:write · Header: Authorization: Basic <base64(keyId:keySecret)> · Optional header: Idempotency-Key: <your unique key, ≤80 chars> · Content-Type: application/json

Request body

FieldTypeRequiredNotes
referencestringnoYour own id for this contact, 1–80 characters. Unique within the business.
namestringnoRequired unless phone is given. Max 300.
businessNamestringnoMax 500.
phonestringnoDigits only, national number without the country code, 4–15 digits. Required unless name is given.
phoneCountryCodestringnoDigits without +, default the store country's (India: "91").
emailstringnoMax 200.
gstNumberstringno15-character GSTIN. Its first two digits are the state code; a contradicting address.stateCode is refused.
rolesstring[]noEach CUSTOMER or SUPPLIER. Default ["CUSTOMER"].
addressobjectno
  line1stringno
  line2stringno
  citystringno
  districtstringno
  statestringno
  stateCodestringno2 digits.
  pincodestringno6 digits.
notestringnoMax 300.

Example request

{
  "reference": "cust-1001",
  "name": "Asha Stores",
  "phone": "9876543210",
  "email": "asha@example.com",
  "gstNumber": "33ABCDE1234F1Z5",
  "address": {
    "line1": "12 Market Road",
    "city": "Chennai",
    "state": "Tamil Nadu",
    "pincode": "600001"
  }
}

Response 201

The envelope (below) with results of:

FieldTypeRequiredNotes
idstring, 24 hex charactersnoThe contact id. Use it as contactId on a sale.
namestring | nullno
businessNamestring | nullnoRegistered name, if a business.
phonestring | nullnoDigits only, national number.
phoneCountryCodestring | nullnoDialling code without +, e.g. "91".
emailstring | nullno
gstNumberstring | nullno15-character GSTIN.
rolesstring[]noEach one of CUSTOMER, SUPPLIER.
addressobjectnoEvery key present, null when unknown.
  line1string | nullno
  line2string | nullno
  citystring | nullno
  districtstring | nullno
  statestring | nullno
  stateCodestring | nullnoGST state code, 2 digits.
  pincodestring | nullno6 digits.
referencestring | nullnoYour own id for this contact, if you gave one.
statusstringnoACTIVE or INACTIVE.
createdAtstringnoISO 8601 UTC.
createdbooleannotrue when this call created the contact.

Example response

{
  "status": true,
  "statusCode": 201,
  "correlationId": "2f6c1e0a9b3d4",
  "results": {
    "id": "66f1a2b3c4d5e6f7a8b9c0d1",
    "name": "Asha Stores",
    "businessName": null,
    "phone": "9876543210",
    "phoneCountryCode": "91",
    "email": "asha@example.com",
    "gstNumber": "33ABCDE1234F1Z5",
    "roles": [
      "CUSTOMER"
    ],
    "address": {
      "line1": "12 Market Road",
      "line2": null,
      "city": "Chennai",
      "district": null,
      "state": "Tamil Nadu",
      "stateCode": "33",
      "pincode": "600001"
    },
    "reference": "cust-1001",
    "status": "ACTIVE",
    "createdAt": "2026-09-18T09:30:00.000Z",
    "created": true
  }
}

GET https://api.negobill.com/v1/contacts

Look up contacts. Exact lookups by reference, phone or gstNumber (any combination, all must match), or a word search. At most 50 rows; this is a lookup, not a way to copy the contact list.

Scope: contacts:read · Header: Authorization: Basic <base64(keyId:keySecret)>

Query parameters

ParameterTypeRequiredNotes
referencestringno
phonestringnoDigits only.
gstNumberstringno
searchstringnoAny word of the name, nickname, business or trade name; digits match the start of the phone. Ignored when an exact key is given.
limitintegerno1–50, default 20.

Response 200

The envelope (below) with results of:

FieldTypeRequiredNotes
contactsobject[]no
  idstring, 24 hex charactersnoThe contact id. Use it as contactId on a sale.
  namestring | nullno
  businessNamestring | nullnoRegistered name, if a business.
  phonestring | nullnoDigits only, national number.
  phoneCountryCodestring | nullnoDialling code without +, e.g. "91".
  emailstring | nullno
  gstNumberstring | nullno15-character GSTIN.
  rolesstring[]noEach one of CUSTOMER, SUPPLIER.
  addressobjectnoEvery key present, null when unknown.
    line1string | nullno
    line2string | nullno
    citystring | nullno
    districtstring | nullno
    statestring | nullno
    stateCodestring | nullnoGST state code, 2 digits.
    pincodestring | nullno6 digits.
  referencestring | nullnoYour own id for this contact, if you gave one.
  statusstringnoACTIVE or INACTIVE.
  createdAtstringnoISO 8601 UTC.

Example response

{
  "status": true,
  "statusCode": 200,
  "correlationId": "2f6c1e0a9b3d4",
  "results": {
    "contacts": [
      {
        "id": "66f1a2b3c4d5e6f7a8b9c0d1",
        "name": "Asha Stores",
        "businessName": null,
        "phone": "9876543210",
        "phoneCountryCode": "91",
        "email": "asha@example.com",
        "gstNumber": "33ABCDE1234F1Z5",
        "roles": [
          "CUSTOMER"
        ],
        "address": {
          "line1": "12 Market Road",
          "line2": null,
          "city": "Chennai",
          "district": null,
          "state": "Tamil Nadu",
          "stateCode": "33",
          "pincode": "600001"
        },
        "reference": "cust-1001",
        "status": "ACTIVE",
        "createdAt": "2026-09-18T09:30:00.000Z"
      }
    ]
  }
}

GET https://api.negobill.com/v1/contacts/{id}

Read a contact.

Scope: contacts:read · Header: Authorization: Basic <base64(keyId:keySecret)>

Path parameters

ParameterTypeRequiredNotes
idstring, 24 hex charactersyes

Response 200

The envelope (below) with results of:

FieldTypeRequiredNotes
idstring, 24 hex charactersnoThe contact id. Use it as contactId on a sale.
namestring | nullno
businessNamestring | nullnoRegistered name, if a business.
phonestring | nullnoDigits only, national number.
phoneCountryCodestring | nullnoDialling code without +, e.g. "91".
emailstring | nullno
gstNumberstring | nullno15-character GSTIN.
rolesstring[]noEach one of CUSTOMER, SUPPLIER.
addressobjectnoEvery key present, null when unknown.
  line1string | nullno
  line2string | nullno
  citystring | nullno
  districtstring | nullno
  statestring | nullno
  stateCodestring | nullnoGST state code, 2 digits.
  pincodestring | nullno6 digits.
referencestring | nullnoYour own id for this contact, if you gave one.
statusstringnoACTIVE or INACTIVE.
createdAtstringnoISO 8601 UTC.

Example response

{
  "status": true,
  "statusCode": 200,
  "correlationId": "2f6c1e0a9b3d4",
  "results": {
    "id": "66f1a2b3c4d5e6f7a8b9c0d1",
    "name": "Asha Stores",
    "businessName": null,
    "phone": "9876543210",
    "phoneCountryCode": "91",
    "email": "asha@example.com",
    "gstNumber": "33ABCDE1234F1Z5",
    "roles": [
      "CUSTOMER"
    ],
    "address": {
      "line1": "12 Market Road",
      "line2": null,
      "city": "Chennai",
      "district": null,
      "state": "Tamil Nadu",
      "stateCode": "33",
      "pincode": "600001"
    },
    "reference": "cust-1001",
    "status": "ACTIVE",
    "createdAt": "2026-09-18T09:30:00.000Z"
  }
}

GET https://api.negobill.com/v1/products

Look up products. An exact code (barcode) lookup, or a word search; at most 50 rows with the stock left at the key's store. Keep your own copy of your catalogue — this call is for looking a product up, not for serving your storefront.

Scope: products:read · Header: Authorization: Basic <base64(keyId:keySecret)>

Query parameters

ParameterTypeRequiredNotes
codestringnoExact product code / barcode. When given, search is ignored.
searchstringnoAny word of the name or search tag; a prefix of each word matches.
limitintegerno1–50, default 20.

Response 200

The envelope (below) with results of:

FieldTypeRequiredNotes
productsobject[]no
  idstring, 24 hex charactersno
  namestringno
  codestring | nullnoBarcode / product code.
  hsnSacstring | nullno
  taxPercentnumbernoOne of 0, 5, 12, 18, 24, 28, 40.
  mrpintegernoPaise.
  salePriceintegernoPaise, GST-inclusive retail price.
  wholesalePriceinteger | nullnoPaise.
  unitstring | nullnoPrimary unit code, e.g. "PCS", "KG".
  isStockTrackedbooleanno
  stockLeftnumber | nullnoUnits left at the key's store; null when the product is not stock-tracked.
  statusstringnoACTIVE or INACTIVE.
  batchesobject[]noOnly on GET /products/{id}, only when the store sells by batch: the batches with stock, oldest first. Name one on a sale line as batchId, or leave it out and the oldest is taken.
    idstring, 24 hex charactersno
    batchNostring | nullno
    stockLeftnumbernoUnits left in this batch.
    mrpinteger | nullnoPaise, this batch's printed MRP.
    salePriceinteger | nullnoPaise, this batch's price.
    expiryDatestring | nullnoYYYY-MM-DD.

Example response

{
  "status": true,
  "statusCode": 200,
  "correlationId": "2f6c1e0a9b3d4",
  "results": {
    "products": [
      {
        "id": "66f1a2b3c4d5e6f7a8b9c0f3",
        "name": "Aashirvaad Atta 5 kg",
        "code": "8901058000123",
        "hsnSac": "1101",
        "taxPercent": 5,
        "mrp": 31000,
        "salePrice": 29500,
        "wholesalePrice": 28000,
        "unit": "PCS",
        "isStockTracked": true,
        "stockLeft": 28,
        "status": "ACTIVE",
        "batches": [
          {
            "id": "66f1a2b3c4d5e6f7a8b9c0b7",
            "batchNo": "B-0912",
            "stockLeft": 28,
            "mrp": 31000,
            "salePrice": 29500,
            "expiryDate": "2027-03-31"
          }
        ]
      }
    ]
  }
}

GET https://api.negobill.com/v1/products/{id}

Read a product. One product with its prices and the stock left at the key's store.

Scope: products:read · Header: Authorization: Basic <base64(keyId:keySecret)>

Path parameters

ParameterTypeRequiredNotes
idstring, 24 hex charactersyes

Response 200

The envelope (below) with results of:

FieldTypeRequiredNotes
idstring, 24 hex charactersno
namestringno
codestring | nullnoBarcode / product code.
hsnSacstring | nullno
taxPercentnumbernoOne of 0, 5, 12, 18, 24, 28, 40.
mrpintegernoPaise.
salePriceintegernoPaise, GST-inclusive retail price.
wholesalePriceinteger | nullnoPaise.
unitstring | nullnoPrimary unit code, e.g. "PCS", "KG".
isStockTrackedbooleanno
stockLeftnumber | nullnoUnits left at the key's store; null when the product is not stock-tracked.
statusstringnoACTIVE or INACTIVE.
batchesobject[]noOnly on GET /products/{id}, only when the store sells by batch: the batches with stock, oldest first. Name one on a sale line as batchId, or leave it out and the oldest is taken.
  idstring, 24 hex charactersno
  batchNostring | nullno
  stockLeftnumbernoUnits left in this batch.
  mrpinteger | nullnoPaise, this batch's printed MRP.
  salePriceinteger | nullnoPaise, this batch's price.
  expiryDatestring | nullnoYYYY-MM-DD.

Example response

{
  "status": true,
  "statusCode": 200,
  "correlationId": "2f6c1e0a9b3d4",
  "results": {
    "id": "66f1a2b3c4d5e6f7a8b9c0f3",
    "name": "Aashirvaad Atta 5 kg",
    "code": "8901058000123",
    "hsnSac": "1101",
    "taxPercent": 5,
    "mrp": 31000,
    "salePrice": 29500,
    "wholesalePrice": 28000,
    "unit": "PCS",
    "isStockTracked": true,
    "stockLeft": 28,
    "status": "ACTIVE",
    "batches": [
      {
        "id": "66f1a2b3c4d5e6f7a8b9c0b7",
        "batchNo": "B-0912",
        "stockLeft": 28,
        "mrp": 31000,
        "salePrice": 29500,
        "expiryDate": "2027-03-31"
      }
    ]
  }
}

POST https://api.negobill.com/v1/sales

Create a sale. Send what was sold — the server prices catalogue lines from the product, computes GST per line, the totals, the rounding and the stock movement, and numbers the bill. Never send totals. A line with productId is a catalogue line (price from the product unless unitPrice is given, which must not be below the product's minimum sale price); a line with name and no productId is a free-text line and needs unitPrice and taxPercent. Sends no payment: a sale is unpaid until a payment is recorded (see POST /sales/{id}/payments). A sale with a contactId may stay unpaid; a sale without one must be paid with the next call. If a COMPLETED sale already carries the same reference it is returned with created:false and nothing is created. Counts in the plan's monthly sale quota like a sale made at the counter.

Scope: sales:write · Header: Authorization: Basic <base64(keyId:keySecret)> · Optional header: Idempotency-Key: <your unique key, ≤80 chars> · Content-Type: application/json

Request body

FieldTypeRequiredNotes
referencestringnoYour order id, 1–80 characters. Unique within the business; makes the call safe to retry.
contactIdstring, 24 hex charactersnoThe customer (from POST /contacts). Required for a sale that will not be paid at once.
docTypestringnoBILL or INVOICE. Omit to let the store's setting decide. INVOICE needs a billing profile with a GST number.
saleDatestringnoYYYY-MM-DD in the store timezone; today or a past day of this or the previous financial year. Default today.
linesobject[]yes1–500 lines.
  productIdstring, 24 hex charactersnoA catalogue product. Either this or name.
  batchIdstring, 24 hex charactersnoCatalogue lines in a batch-selling store: the batch to sell from (see GET /products/{id}). Left out, the oldest batch with stock is taken.
  namestringnoFree-text line name, max 1000. Either this or productId.
  kindstringnoFree-text lines only: PRODUCT or SERVICE, default SERVICE.
  quantitynumberyesUp to 4 decimals.
  unitPriceintegernoPaise, GST-inclusive, per unit. Required for free-text lines; optional override for catalogue lines. 0 is allowed (free item).
  taxPercentnumbernoFree-text lines only: one of 0, 5, 12, 18, 24, 28, 40. Default 0. Catalogue lines take the product's.
  hsnSacstringnoFree-text lines only, 4–8 digits.
  unitstringnoCatalogue lines: a sale-unit tier name of the product (e.g. "BOX"); free-text lines: a label printed beside the quantity.
  notestringnoPrinted under the line, max 500 — the phone model a skin is for, an engraving text, a measurement.
  addOnsstring[]noCatalogue lines only: keys of the product's add-on options to charge with this line (see GET /products/{id} → addOns). Each becomes a SERVICE line under the product at the option's catalogue price; an unknown key is refused with NB-B-SAL-1024; while the shop has add-on options switched off (Settings → Product) any key is refused with NB-B-SAL-1026.
overallDiscountintegernoPaise taken off the whole bill, spread across the lines with GST recomputed per line.
notestringnoMax 300, printed on the bill.

Example request

{
  "reference": "order-5501",
  "contactId": "66f1a2b3c4d5e6f7a8b9c0d1",
  "lines": [
    {
      "productId": "66f1a2b3c4d5e6f7a8b9c0f3",
      "quantity": 2
    },
    {
      "name": "Delivery charge",
      "kind": "SERVICE",
      "quantity": 1,
      "unitPrice": 5000,
      "taxPercent": 18,
      "hsnSac": "996812"
    }
  ],
  "note": "Web order 5501"
}

Response 201

The envelope (below) with results of:

FieldTypeRequiredNotes
idstring, 24 hex charactersnoThe sale id.
saleNostringnoThe bill / invoice number as printed, e.g. "A20262027104".
docTypestringnoBILL or INVOICE (Tax Invoice).
statusstringnoCOMPLETED or REVERSED (cancelled).
saleDatestringnoISO 8601 UTC instant.
saleDaystringnoYYYY-MM-DD in the store timezone.
referencestring | nullnoYour reference, if you gave one.
contactIdstring, 24 hex characters | nullno
customerobject | nullnoThe customer as snapshotted on the sale.
  namestring | nullno
  phonestring | nullno
  gstNumberstring | nullno
linesobject[]noIn the order NegoBill stores them (free-text lines before catalogue lines) — match by productId or name, not by position.
  productIdstring, 24 hex characters | nullnonull for a free-text line.
  namestringno
  kindstringnoPRODUCT or SERVICE.
  quantitynumberno
  unitstring | nullno
  unitPriceintegernoPaise, GST-inclusive.
  mrpinteger | nullnoPaise.
  taxPercentnumberno
  taxAmountintegernoPaise, the GST inside this line.
  amountintegernoPaise, line total including GST.
  notestring | nullnoThe line note as printed under the name (e.g. the phone model a skin was cut for).
  lineGroupstring | nullnoSet on a product line that carries add-on options and on each of its option lines — the same value groups them.
  addOnKeystring | nullnoOn an add-on option line: the option key from the product (e.g. LOGO-CUT). null on ordinary lines.
totalsobjectnoAll paise.
  taxableintegernoSum of line amounts before GST.
  taxintegernoTotal GST.
  totalintegernotaxable + tax.
  roundOffintegernoPaise added (or removed, negative) to reach a whole rupee.
  grandTotalintegernoWhat the customer pays. Whole rupees, in paise.
  amountInWordsstringno
paidintegernoPaise received so far.
dueintegernoPaise still unpaid. 0 = settled.
notestring | nullno
createdAtstringnoISO 8601 UTC.
createdbooleannoOnly on POST: true when this call made the sale, false when a sale with the same reference already existed and was returned instead.

Example response

{
  "status": true,
  "statusCode": 201,
  "correlationId": "2f6c1e0a9b3d4",
  "results": {
    "id": "66f1a2b3c4d5e6f7a8b9c0e2",
    "saleNo": "A20262027104",
    "docType": "INVOICE",
    "status": "COMPLETED",
    "saleDate": "2026-09-18T09:31:12.000Z",
    "saleDay": "2026-09-18",
    "reference": "order-5501",
    "contactId": "66f1a2b3c4d5e6f7a8b9c0d1",
    "customer": {
      "name": "Asha Stores",
      "phone": "9876543210",
      "gstNumber": "33ABCDE1234F1Z5"
    },
    "lines": [
      {
        "productId": "66f1a2b3c4d5e6f7a8b9c0f3",
        "name": "Aashirvaad Atta 5 kg",
        "kind": "PRODUCT",
        "quantity": 2,
        "unit": "PCS",
        "unitPrice": 29500,
        "mrp": 31000,
        "taxPercent": 5,
        "taxAmount": 2810,
        "amount": 59000
      },
      {
        "productId": null,
        "name": "Delivery charge",
        "kind": "SERVICE",
        "quantity": 1,
        "unit": null,
        "unitPrice": 5000,
        "mrp": null,
        "taxPercent": 18,
        "taxAmount": 763,
        "amount": 5000
      }
    ],
    "totals": {
      "taxable": 60427,
      "tax": 3573,
      "total": 64000,
      "roundOff": 0,
      "grandTotal": 64000,
      "amountInWords": "Six Hundred Forty Rupees Only"
    },
    "paid": 0,
    "due": 64000,
    "note": "Web order 5501",
    "createdAt": "2026-09-18T09:31:12.000Z",
    "created": true
  }
}

GET https://api.negobill.com/v1/sales

Look up sales. By reference or saleNo (exact), by contactId, or by a day range; newest first, at most 50.

Scope: sales:read · Header: Authorization: Basic <base64(keyId:keySecret)>

Query parameters

ParameterTypeRequiredNotes
referencestringno
saleNostringno
contactIdstring, 24 hex charactersno
fromstringnoYYYY-MM-DD, inclusive.
tostringnoYYYY-MM-DD, inclusive.
limitintegerno1–50, default 20.

Response 200

The envelope (below) with results of:

FieldTypeRequiredNotes
salesobject[]no
  idstring, 24 hex charactersnoThe sale id.
  saleNostringnoThe bill / invoice number as printed, e.g. "A20262027104".
  docTypestringnoBILL or INVOICE (Tax Invoice).
  statusstringnoCOMPLETED or REVERSED (cancelled).
  saleDatestringnoISO 8601 UTC instant.
  saleDaystringnoYYYY-MM-DD in the store timezone.
  referencestring | nullnoYour reference, if you gave one.
  contactIdstring, 24 hex characters | nullno
  customerobject | nullnoThe customer as snapshotted on the sale.
    namestring | nullno
    phonestring | nullno
    gstNumberstring | nullno
  linesobject[]noIn the order NegoBill stores them (free-text lines before catalogue lines) — match by productId or name, not by position.
    productIdstring, 24 hex characters | nullnonull for a free-text line.
    namestringno
    kindstringnoPRODUCT or SERVICE.
    quantitynumberno
    unitstring | nullno
    unitPriceintegernoPaise, GST-inclusive.
    mrpinteger | nullnoPaise.
    taxPercentnumberno
    taxAmountintegernoPaise, the GST inside this line.
    amountintegernoPaise, line total including GST.
    notestring | nullnoThe line note as printed under the name (e.g. the phone model a skin was cut for).
    lineGroupstring | nullnoSet on a product line that carries add-on options and on each of its option lines — the same value groups them.
    addOnKeystring | nullnoOn an add-on option line: the option key from the product (e.g. LOGO-CUT). null on ordinary lines.
  totalsobjectnoAll paise.
    taxableintegernoSum of line amounts before GST.
    taxintegernoTotal GST.
    totalintegernotaxable + tax.
    roundOffintegernoPaise added (or removed, negative) to reach a whole rupee.
    grandTotalintegernoWhat the customer pays. Whole rupees, in paise.
    amountInWordsstringno
  paidintegernoPaise received so far.
  dueintegernoPaise still unpaid. 0 = settled.
  notestring | nullno
  createdAtstringnoISO 8601 UTC.
  createdbooleannoOnly on POST: true when this call made the sale, false when a sale with the same reference already existed and was returned instead.

Example response

{
  "status": true,
  "statusCode": 200,
  "correlationId": "2f6c1e0a9b3d4",
  "results": {
    "sales": [
      {
        "id": "66f1a2b3c4d5e6f7a8b9c0e2",
        "saleNo": "A20262027104",
        "docType": "INVOICE",
        "status": "COMPLETED",
        "saleDate": "2026-09-18T09:31:12.000Z",
        "saleDay": "2026-09-18",
        "reference": "order-5501",
        "contactId": "66f1a2b3c4d5e6f7a8b9c0d1",
        "customer": {
          "name": "Asha Stores",
          "phone": "9876543210",
          "gstNumber": "33ABCDE1234F1Z5"
        },
        "lines": [
          {
            "productId": "66f1a2b3c4d5e6f7a8b9c0f3",
            "name": "Aashirvaad Atta 5 kg",
            "kind": "PRODUCT",
            "quantity": 2,
            "unit": "PCS",
            "unitPrice": 29500,
            "mrp": 31000,
            "taxPercent": 5,
            "taxAmount": 2810,
            "amount": 59000
          },
          {
            "productId": null,
            "name": "Delivery charge",
            "kind": "SERVICE",
            "quantity": 1,
            "unit": null,
            "unitPrice": 5000,
            "mrp": null,
            "taxPercent": 18,
            "taxAmount": 763,
            "amount": 5000
          }
        ],
        "totals": {
          "taxable": 60427,
          "tax": 3573,
          "total": 64000,
          "roundOff": 0,
          "grandTotal": 64000,
          "amountInWords": "Six Hundred Forty Rupees Only"
        },
        "paid": 0,
        "due": 64000,
        "note": "Web order 5501",
        "createdAt": "2026-09-18T09:31:12.000Z"
      }
    ]
  }
}

GET https://api.negobill.com/v1/sales/{id}

Read a sale. Including what is paid and what is still due.

Scope: sales:read · Header: Authorization: Basic <base64(keyId:keySecret)>

Path parameters

ParameterTypeRequiredNotes
idstring, 24 hex charactersyes

Response 200

The envelope (below) with results of:

FieldTypeRequiredNotes
idstring, 24 hex charactersnoThe sale id.
saleNostringnoThe bill / invoice number as printed, e.g. "A20262027104".
docTypestringnoBILL or INVOICE (Tax Invoice).
statusstringnoCOMPLETED or REVERSED (cancelled).
saleDatestringnoISO 8601 UTC instant.
saleDaystringnoYYYY-MM-DD in the store timezone.
referencestring | nullnoYour reference, if you gave one.
contactIdstring, 24 hex characters | nullno
customerobject | nullnoThe customer as snapshotted on the sale.
  namestring | nullno
  phonestring | nullno
  gstNumberstring | nullno
linesobject[]noIn the order NegoBill stores them (free-text lines before catalogue lines) — match by productId or name, not by position.
  productIdstring, 24 hex characters | nullnonull for a free-text line.
  namestringno
  kindstringnoPRODUCT or SERVICE.
  quantitynumberno
  unitstring | nullno
  unitPriceintegernoPaise, GST-inclusive.
  mrpinteger | nullnoPaise.
  taxPercentnumberno
  taxAmountintegernoPaise, the GST inside this line.
  amountintegernoPaise, line total including GST.
  notestring | nullnoThe line note as printed under the name (e.g. the phone model a skin was cut for).
  lineGroupstring | nullnoSet on a product line that carries add-on options and on each of its option lines — the same value groups them.
  addOnKeystring | nullnoOn an add-on option line: the option key from the product (e.g. LOGO-CUT). null on ordinary lines.
totalsobjectnoAll paise.
  taxableintegernoSum of line amounts before GST.
  taxintegernoTotal GST.
  totalintegernotaxable + tax.
  roundOffintegernoPaise added (or removed, negative) to reach a whole rupee.
  grandTotalintegernoWhat the customer pays. Whole rupees, in paise.
  amountInWordsstringno
paidintegernoPaise received so far.
dueintegernoPaise still unpaid. 0 = settled.
notestring | nullno
createdAtstringnoISO 8601 UTC.
createdbooleannoOnly on POST: true when this call made the sale, false when a sale with the same reference already existed and was returned instead.

Example response

{
  "status": true,
  "statusCode": 200,
  "correlationId": "2f6c1e0a9b3d4",
  "results": {
    "id": "66f1a2b3c4d5e6f7a8b9c0e2",
    "saleNo": "A20262027104",
    "docType": "INVOICE",
    "status": "COMPLETED",
    "saleDate": "2026-09-18T09:31:12.000Z",
    "saleDay": "2026-09-18",
    "reference": "order-5501",
    "contactId": "66f1a2b3c4d5e6f7a8b9c0d1",
    "customer": {
      "name": "Asha Stores",
      "phone": "9876543210",
      "gstNumber": "33ABCDE1234F1Z5"
    },
    "lines": [
      {
        "productId": "66f1a2b3c4d5e6f7a8b9c0f3",
        "name": "Aashirvaad Atta 5 kg",
        "kind": "PRODUCT",
        "quantity": 2,
        "unit": "PCS",
        "unitPrice": 29500,
        "mrp": 31000,
        "taxPercent": 5,
        "taxAmount": 2810,
        "amount": 59000
      },
      {
        "productId": null,
        "name": "Delivery charge",
        "kind": "SERVICE",
        "quantity": 1,
        "unit": null,
        "unitPrice": 5000,
        "mrp": null,
        "taxPercent": 18,
        "taxAmount": 763,
        "amount": 5000
      }
    ],
    "totals": {
      "taxable": 60427,
      "tax": 3573,
      "total": 64000,
      "roundOff": 0,
      "grandTotal": 64000,
      "amountInWords": "Six Hundred Forty Rupees Only"
    },
    "paid": 0,
    "due": 64000,
    "note": "Web order 5501",
    "createdAt": "2026-09-18T09:31:12.000Z"
  }
}

GET https://api.negobill.com/v1/sales/{id}/paper

The bill as HTML. The printable A4 bill, rendered by NegoBill from the sale exactly as the shop prints it (text/html, not JSON).

Scope: sales:read · Header: Authorization: Basic <base64(keyId:keySecret)>

Path parameters

ParameterTypeRequiredNotes
idstring, 24 hex charactersyes

Response 200

text/html — a complete HTML document.

Example response

<!doctype html><html>…</html>

POST https://api.negobill.com/v1/sales/{id}/share

A public link to the bill. A link the customer opens with no login (the same link the shop's Share button makes). Its life follows the shop's Settings → Sales → Share link expiry; a cancelled or edited sale retires the link.

Scope: sales:read · Header: Authorization: Basic <base64(keyId:keySecret)>

Path parameters

ParameterTypeRequiredNotes
idstring, 24 hex charactersyes

Response 200

The envelope (below) with results of:

FieldTypeRequiredNotes
urlstringno
expiresAtstring | nullnoISO 8601 UTC; null = never.

Example response

{
  "status": true,
  "statusCode": 200,
  "correlationId": "2f6c1e0a9b3d4",
  "results": {
    "url": "https://bill.negobill.com/share/sale/eyJ2Ijp7ImlkIjoi…",
    "expiresAt": "2026-10-18T09:31:12.000Z"
  }
}

POST https://api.negobill.com/v1/sales/{id}/payments

Record a payment. Records money received against this sale under one of the business's payment methods (by name, case-insensitive — the error lists the names when yours is unknown). The amount must not exceed what is due. If a receipt already carries the same reference it is returned with created:false.

Scope: payments:write · Header: Authorization: Basic <base64(keyId:keySecret)> · Optional header: Idempotency-Key: <your unique key, ≤80 chars> · Content-Type: application/json

Path parameters

ParameterTypeRequiredNotes
idstring, 24 hex charactersyesThe sale.

Request body

FieldTypeRequiredNotes
referencestringnoYour payment id, 1–80 characters. Unique within the business.
amountintegeryesPaise, at most the sale's due.
methodstringyesA payment method name of the business, e.g. "UPI", "Cash", "Bank transfer", "Card".
notestringnoMax 300.

Example request

{
  "reference": "pay-5501",
  "amount": 64000,
  "method": "UPI"
}

Response 201

The envelope (below) with results of:

FieldTypeRequiredNotes
idstring, 24 hex charactersnoThe receipt id.
receiptNostringno
amountintegernoPaise.
methodstring | nullnoThe payment method name.
saleIdstring, 24 hex characters | nullno
referencestring | nullno
receiptDatestringnoISO 8601 UTC.
dueintegernoPaise still unpaid on the sale after this receipt.
createdbooleannoOnly on POST: false when a receipt with the same reference already existed and was returned instead.

Example response

{
  "status": true,
  "statusCode": 201,
  "correlationId": "2f6c1e0a9b3d4",
  "results": {
    "id": "66f1a2b3c4d5e6f7a8b9c1a4",
    "receiptNo": "R20262027211",
    "amount": 64000,
    "method": "UPI",
    "saleId": "66f1a2b3c4d5e6f7a8b9c0e2",
    "reference": "pay-5501",
    "receiptDate": "2026-09-18T09:32:40.000Z",
    "due": 0,
    "created": true
  }
}

GET https://api.negobill.com/v1/sales/{id}/payments

Payments on a sale.

Scope: payments:read · Header: Authorization: Basic <base64(keyId:keySecret)>

Path parameters

ParameterTypeRequiredNotes
idstring, 24 hex charactersyes

Response 200

The envelope (below) with results of:

FieldTypeRequiredNotes
paymentsobject[]no
  idstring, 24 hex charactersnoThe receipt id.
  receiptNostringno
  amountintegernoPaise.
  methodstring | nullnoThe payment method name.
  saleIdstring, 24 hex characters | nullno
  referencestring | nullno
  receiptDatestringnoISO 8601 UTC.
  dueintegernoPaise still unpaid on the sale after this receipt.
  createdbooleannoOnly on POST: false when a receipt with the same reference already existed and was returned instead.
dueintegernoPaise still unpaid.

Example response

{
  "status": true,
  "statusCode": 200,
  "correlationId": "2f6c1e0a9b3d4",
  "results": {
    "payments": [
      {
        "id": "66f1a2b3c4d5e6f7a8b9c1a4",
        "receiptNo": "R20262027211",
        "amount": 64000,
        "method": "UPI",
        "saleId": "66f1a2b3c4d5e6f7a8b9c0e2",
        "reference": "pay-5501",
        "receiptDate": "2026-09-18T09:32:40.000Z",
        "due": 0
      }
    ],
    "due": 0
  }
}

Errors

HTTPcodeMeaningWhat to do
400NB-B-API-1000External API request validation failedFix the request (details lists each field) and retry with a NEW Idempotency-Key.
401NB-B-API-1001No credentials — Authorization: Basic <base64(keyId:keySecret)> missing or malformedSend the Authorization header. Do not retry unchanged.
401NB-B-API-1002Key ID unknown, secret wrong, or the key was revokedCheck the Key ID and secret in the console; a revoked key never works again. Alert a human.
403NB-B-API-1003The API Access add-on is not active on this business (plan lacks it, or the module is switched off)The business must add the API Access add-on in Settings → Billing & Plans (Plus and above), or switch the API module on. Alert a human.
403NB-B-API-1004The key lacks the scope this call needsAsk the owner to add the scope to the key in Settings → API Access. Do not retry unchanged.
429NB-B-API-1005Rate limit reached for this keyWait for Retry-After seconds, then retry the same request.
409NB-B-API-1006Idempotency-Key reused with a different body, or the first request is still runningA key reused with a different body: use a new key. "Still being processed": wait a second and retry the same request.
404NB-B-API-1007Not found in this businessThe id is not in this business. Do not retry.
403NB-B-API-1008The calling IP is not on the key allowlistAdd the calling server's IP to the key's allowlist in the console. Alert a human.
400NB-B-SAL-1000Sale validation failed (a line, a price below the product's minimum, a bad date)Fix the request; details names the field.
404NB-B-SAL-1002Store or billing profile not foundAlert a human: the key's store is not set up.
400NB-B-SAL-1012INVOICE asked for but the billing profile has no GST numberSend docType BILL, or omit it.
403NB-B-PLN-1006The plan's monthly sale quota is reachedStop creating sales; alert a human — the business must upgrade its plan.
400NB-B-PAY-1000Payment validation failed (amount above the due, unknown method)Fix the request; details says what.
400NB-B-CON-1000Contact validation failedFix the request.
409NB-B-CON-1001A contact with this phone already existsLook the contact up (GET /contacts?phone=) and use its id.
500NB-B-CORE-1000An internal errorRetry with backoff (same Idempotency-Key); after three failures alert a human and quote correlationId.

Rule of thumb: 400/404/409 — fix the request, do not retry unchanged; 401/403 — a credential, scope, plan or allowlist matter for a human; 429 — wait Retry-After and retry; 5xx — retry with backoff and the same Idempotency-Key.

Versioning

This is v1. Fields are only ever added; a removed or renamed field, a changed type or a changed status code would ship as /v2 with this page kept for v1 and a deprecation date announced here.

Changelog