TendersPricing
Partners

VEXORS, the AI tendering platform for construction.

Product

  • Features
  • Pricing
  • For buyers
  • For suppliers
  • Industries

Solutions

  • AI procurement software
  • RFQ software
  • RFP management
  • E-sourcing platform
  • Bid evaluation software
  • Supplier management
  • Tender management
  • E-procurement software
  • All solutions

Compare

  • Excel comparison sheet vs VEXORS
  • Email vs structured RFQ/RFP/RFI
  • ERP module vs platform
  • Enterprise suite vs VEXORS
  • Marketplace vs tendering platform
  • Legacy ERP vs VEXORS
  • SAP Ariba alternative
  • Oracle Aconex alternative
  • Procore alternative
  • BuildingConnected alternative
  • ProcurePro alternative

Company

  • Contact
  • Partners

Resources

  • Blog
  • Templates
  • Glossary
  • Maturity assessment
  • Open tenders
  • ROI calculator
  • Knowledge Hub
  • Security

Legal

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • Refund Policy
  • Service Level Agreement
  • Data Processing Addendum
  • Copyright Policy
  • Brand and Trademark Policy
  • Referral Program Terms

© 2026 VEXORS FZC, United Arab Emirates. All rights reserved.

Enterprise-grade security · Built for MENA

Getting started

  • What is VEXORS?
  • Create your account and choose your role
  • Complete your company profile
  • Understanding your Trust Score
  • A guided tour of VEXORS

For buyers

  • Create a Request: RFQ, RFP, or RFI
  • Build your Bill of Quantities
  • Add a Questionnaire
  • Invite suppliers, or open it to the network
  • Set up approval steps
  • Review bids and read AI Scoring
  • Compare bids and responses
  • Award a contract
  • Rate suppliers after an award
  • Save and reuse request templates
  • Edit, amend, or cancel a request
  • Run Q&A and announcements during bidding
  • Find and connect with suppliers in Discover
  • Onboard suppliers with Connect forms
  • Track your work with tasks

Construction projects

  • Run a construction project on VEXORS
  • Import your BoQ from a spreadsheet
  • Manage project documents and drawings
  • Split into trade packages
  • Review the commercial position
  • Price, mark up, and bill your client
  • Understand construction pricing on VEXORS

For suppliers

  • Find Opportunities
  • Submit a Bid
  • Use the Bid Quality Coach
  • Track Your Bids
  • When You Win, and When You Do Not
  • Build Your Catalog
  • Raise Your Trust Score and Get Verified
  • Respond to a buyer's onboarding form
  • Send a service offer to a buyer
  • Manage your customers and connections

AI tools

  • How AI works on VEXORS
  • AI RFQ Drafter
  • Questionnaire Assistant
  • Pre-Publish Insights
  • AI Supplier Matching
  • AI Bid Insights
  • AI Spend Summary
  • Partner Intelligence
  • AI Bid Analysis
  • Supplier Summary

Trust & security

  • Trust and safety on VEXORS
  • Get your business Verified
  • Ratings and reviews, both ways
  • What others can and cannot see

Account & billing

  • Plans and what they unlock
  • Manage your subscription
  • Team members and roles
  • AI credits
  • Payment and invoices
  • Currency settings
  • Referrals

Help center

  • Account and sign-in help
  • Common questions
  • Contact support
  • Set up two-factor authentication
  • Manage your active sessions
  • Choose your notification and email preferences
  • Billing and payment help
  • File a complaint or dispute

Developer docs

  • Developer documentation
  • ERP Connections
Developer docs· Guide 1 of 2

Developer documentation

Webhooks and API keys are live on the Scale plan today: signed, retried webhook deliveries you can verify, and integration endpoints your own systems can call with a key. Here is how to receive webhooks and how to start with API keys.

~9 min
DocsDeveloper docsDeveloper documentation·Last updated 2026-09-30

Webhooks are a shipped, working feature on VEXORS today, available on the Scale plan. Calling VEXORS from your own systems with an API key is a separate feature, also available on the Scale plan.

Webhooks (Scale, available now)

Configure webhooks under Settings then Webhooks (company admins only). From there you can:

  • Add an endpoint: a name, an HTTPS URL for VEXORS to call, and the events you want, chosen from the catalogue (request, bid, award, rating, opportunity and service-offer events, for example bid.submitted and award.issued). Up to 20 endpoints per company. Your endpoint receives an event only when your company is one of the parties VEXORS notifies about it in the app: a buyer receives bid.submitted for bids on its own requests, a supplier receives bid.shortlisted for its own bid, and an event that concerns both sides, such as award.issued, goes to both. A published request reaches only the suppliers it is visible to: when the request is private, that means the invited suppliers. When a request closes or reopens, suppliers holding a draft bid on it are told as well.
  • Copy the endpoint's signing secret the one time it is shown. Every delivery is signed with it (see below). You can rotate it later; the new secret is shown once and the old one stops working at that moment, so update your receiver first. If two people rotate the same endpoint at the same moment, only one rotation happens and the other is asked to reload.
  • Send a test delivery and see the result immediately: HTTP status, duration, and the headers VEXORS sent. A test also works on a disabled endpoint: it is really sent, the endpoint stays disabled, and a test never changes an endpoint's health.
  • Open the deliveries list for an endpoint: every delivery with its state, attempts, status code and the payload as sent (sensitive values redacted), and redeliver any finished delivery. A redelivery is a new delivery of the same event, linked to the original.
  • Disable and enable an endpoint, or delete it. Disabling or deleting cancels the deliveries that were still waiting to be sent; after you re-enable an endpoint you can redeliver them from its deliveries list.

The page is Scale-only. On Grow and Explore it shows an upgrade prompt instead.

Receiving webhooks

Each delivery is an HTTPS POST to your endpoint with a JSON body:

{
  "id": "6f3b…",                 // delivery id — the same on every retry of this delivery
  "event": "bid.submitted",
  "event_id": "…",               // the source event; identical across retries and redeliveries
  "occurred_at": "2026-09-29T10:15:00.000Z",   // when the event happened, not when this attempt was sent
  "company_id": "…",
  "delivery": { "attempt": 1, "redelivery_of": null },
  "data": { … }                  // the event payload
}

What data contains. Only the fields VEXORS publishes for that event and for your side of it. You never receive the list of other companies matched to a request, another company's user ids or people's names, or the position of an approval inside someone's approval chain. If you hold a draft bid on a request that closes or reopens, the event lists your own draft only. A field that VEXORS adds internally later is not sent to you until it is published for your side, so treat unknown fields as optional and do not depend on fields that are not documented for your event.

A withdrawn bid you never saw. bid.withdrawn tells a buyer that a supplier withdrew a bid on one of its requests. If the bid had been submitted to you, the event names the supplier and the bid. If the supplier withdrew a bid that never reached you (a draft, or a bid still waiting for the supplier's own internal approval), you still receive the event, but its data says only which request it concerns and when, with a flag telling you the bid was never visible to you:

{
  "request_id": "…",
  "buyer_company_id": "…",
  "rfx_ref": "…",
  "withdrawn_at": "2026-09-30T09:00:00.000Z",
  "was_visible_to_buyer": false
}

Since 30 September 2026 the following fields are no longer sent to the company that used to receive them:

request.closed, request.reopened          matched_company_ids, affected_draft_bids
request.evaluation-started                matched_company_ids
request.details-updated                   matched_company_ids
request.approval-approved, -rejected      step_id, step_number
bid.submitted                             assigned_am_user_id, performed_by_user_id, actor_name
rating.submitted                          rater_user_id, actor_name

From the same date, events about a supplier's own bid, invitation, award withdrawal or service offer (bid.shortlisted, bid.unshortlisted, bid.under-review, bid.approval-approved, request.invitation-sent, request.invitation-rescinded, award.rescinded, service-offer.accepted, service-offer.converted) and request.published are delivered to the supplier's endpoints, not the buyer's.

Headers on every delivery

HeaderMeaning
X-Vexors-Delivery-IdThe delivery id. Stable across retries of the same delivery; use it to ignore duplicates.
X-Vexors-EventThe event code, for example bid.submitted. A test delivery sends webhook.test.
X-Vexors-Event-IdThe id of the underlying event. A manual redelivery carries a new delivery id but the same event id, so use the event id to recognise an event you have already processed. Every occurrence has its own event id: a request that is reopened twice, or a supplier invited again after an invitation was withdrawn, sends two separate events.
X-Vexors-TimestampUnix seconds when this attempt was sent (retries get a fresh timestamp).
X-Vexors-AttemptAttempt number, starting at 1.
X-Vexors-Signaturet=<unix seconds>,v1=<hex HMAC-SHA256> — see verification below. Endpoints created before September 2026 receive the older sha256=<hex> form here until you switch them to v1 in Edit.
X-Vexors-Signature-V1Only on those older endpoints: the t=…,v1=… signature, so you can move your verification over before switching.
X-Vexors-Redelivery-OfOnly on a manual redelivery: the id of the original delivery.
X-Idempotency-KeyOnly on those older endpoints: the event id, exactly as they received it before. It goes away when you switch to v1; use X-Vexors-Event-Id instead.
User-AgentVexors-Webhooks/1.0 (+https://vexors.com)

Verify the signature. Compute HMAC-SHA256 with your endpoint's secret over the string <t>.<raw body> — the timestamp from the header, a dot, and the request body exactly as received (do not parse and re-serialise it first) — and compare it to v1 in constant time. Reject the delivery if the timestamp is more than 300 seconds from your clock. Then record the delivery id and the event id, and ignore a repeat of either.

A bad signature header must be a rejected delivery, never a crash in your service. Answer 401 when the header is missing, arrives more than once, is unusually long, has a timestamp that is not a plain positive whole number, has a signature that is not exactly 64 hexadecimal characters, is outside your time tolerance, or does not match. The example below checks the shape of the header before it compares anything. If you read the time tolerance from configuration, make sure a missing value cannot turn the check off; the example falls back to 300 seconds.

import { createHmac, timingSafeEqual } from 'node:crypto';

// rawBody: Buffer or string of the request body, untouched
export function verifyVexorsWebhook(rawBody, signatureHeader, secret, toleranceSeconds = 300) {
  const match = /^t=(\d+),v1=([0-9a-f]{64})$/i.exec(signatureHeader ?? '');
  if (!match) return false;
  const t = Number(match[1]);
  // a tolerance that is not a number would accept every timestamp: fall back to the default
  const tolerance = Number.isFinite(toleranceSeconds) && toleranceSeconds >= 0 ? toleranceSeconds : 300;
  if (Math.abs(Math.floor(Date.now() / 1000) - t) > tolerance) return false;
  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
  const a = Buffer.from(expected, 'hex');
  const b = Buffer.from(match[2], 'hex');
  return a.length === b.length && timingSafeEqual(a, b);
}

// Express example: keep the raw body, verify, then dedupe on the delivery id and the event id
app.post('/vexors', express.raw({ type: 'application/json' }), (req, res) => {
  if (!verifyVexorsWebhook(req.body, req.get('X-Vexors-Signature'), process.env.VEXORS_WEBHOOK_SECRET)) {
    return res.status(401).end();
  }
  const deliveryId = req.get('X-Vexors-Delivery-Id'); // same on every retry of one delivery
  const eventId = req.get('X-Vexors-Event-Id');       // same on a manual redelivery of the event
  if (alreadyProcessed(deliveryId) || alreadyProcessed(eventId)) return res.status(200).end();
  handle(JSON.parse(req.body.toString('utf8')));
  markProcessed(deliveryId);
  markProcessed(eventId);
  res.status(200).end();
});

For an older endpoint still on the sha256= form, the expected value is HMAC-SHA256 over the raw body alone (no timestamp), compared the same way; that form has no replay protection, so switch to v1 when you can. Older endpoints also keep two things they always received: a top-level timestamp field in the body, equal to the time of the event, and the X-Idempotency-Key header. Both stop when you switch to v1.

Respond quickly with a 2xx. VEXORS waits up to 10 seconds for your response; only a 2xx status counts as delivered. Do your processing after you have answered, or keep it short.

Retries. A delivery that fails with a network error, a timeout, a 5xx, a 408 or a 429 is retried up to 5 attempts in total, waiting about 30 seconds, then 1, 2 and 4 minutes (with some jitter). Any other 4xx is treated as final on the first attempt. Deliveries can arrive out of order and, rarely, more than once — always deduplicate on the delivery id, and on the event id if you also want to ignore a manual redelivery of something you already processed. A problem on the VEXORS side is never counted against your endpoint and does not use up an attempt: the delivery waits and is sent once the problem is fixed. Only if the problem lasts more than three days is the delivery listed as failed, and you can still redeliver it. A delivery that fails on every attempt is kept for 90 days on the endpoint's deliveries list, where you can redeliver it after fixing your receiver.

Automatic disabling. If 10 deliveries in a row fail on every attempt, VEXORS disables the endpoint and notifies your company admins in the app and by email. Once your receiver is fixed, re-enable it from Settings then Webhooks (the endpoint's menu, Enable); the failure counter resets. A successful delivery also resets the counter, and test deliveries never count toward it. A delivery rejected only because you rotated the secret while it was on its way is retried with the new secret and is not counted either.

Event catalogue. The full list of event codes, grouped by area, is the one shown when you add or edit an endpoint; the codes are stable and use the area.action form (request.published, bid.shortlisted, award.issued, rating.submitted, opportunity.confirmed, service-offer.accepted, …).

API keys (Scale, available now)

Your own systems can call VEXORS directly, rather than only receiving pushed events. A company admin creates keys under Settings then API Keys: each key gets a name and the areas it may read or change (requests, bids, service offers, catalog, Connect, and company discovery), and its secret is shown once. Send the key in the x-vexors-api-key header of each call to the integration endpoints. A key acts as the member who created it, with that member's permissions, so it can never do more than that person can.

The page is Scale-only. On Grow and Explore it shows an upgrade prompt instead.

This page does not list the individual endpoints yet. Contact us for the endpoint reference for the areas you need.

Planning an integration

If you are planning an integration and want to talk it through, get in touch and we will help you scope it, whether that means webhooks, API keys, or both.

Contact us about integrations
Was this page helpful?
NextERP Connections

Related guides

ERP ConnectionsConnect your ERP to VEXORS so an awarded contract reaches purchasing as a draft purchase order and your vendor master flows into your VEXORS directory. What it does, what is never sent, and what to prepare on the ERP side.

Get started with VEXORS

Set up your account and explore the platform.

On this page

  • Webhooks (Scale, available now)
  • Receiving webhooks
  • API keys (Scale, available now)
  • Planning an integration