OwlOps Vendor API
Integrate your external systems with the powerful data captured in OwlOps
Beta. The Vendor API is in beta. It is live and supported, but endpoints, fields and behaviour may still change, and we will tell you before anything breaking lands. Please send questions, problems and feedback to support@owlops.com — including during evaluation. We would rather hear about a rough edge early than have you work around it.
What this API is for
If OwlOps customers dispatch work to you, this API lets your own systems do what your team would otherwise do by hand in the OwlOps vendor screen:
- Pull the tasks assigned to you, across all of your customers
- See their full history, costs and attachments
- Update them — acknowledge, assign a technician, check in and out, submit quotes and invoices, request follow-up work, decline, and close
One API key covers every customer who sends you work. You do not need a key per customer.
A note on vocabulary: OwlOps calls these tasks. Other systems call the same thing a work order or a service request.
1. Get an API key
API keys are created inside OwlOps, by an administrator on your own account:
- Sign in to OwlOps
- Go to Setup → API Keys
- Click + Add Key
- Set Key Type to Vendor — this matters, see the warning below
- Give it a label describing the integration (e.g. "Acme dispatch system")
- Click Generate Key
The key is shown once. Copy it immediately and store it somewhere safe — OwlOps cannot show it to you again. If you lose it, use Recycle to issue a replacement, which also stops the old one working.
Key Type must be Vendor. A Standard key is a valid key, but it is scoped to your own internal work and the vendor endpoints will reject it with
403. If every call returns403 This endpoint requires a vendor API key, this is why.
If you do not have an OwlOps login, or you cannot see Setup → Company, contact support@owlops.com and we will sort it out.
2. Base URL and authentication
https://api-owlops-public-bugrb4gxeqcghqh5.eastus2-01.azurewebsites.net
Send your key in the X-Api-Key header on every request. There is no login step and no token to refresh.
curl -H "X-Api-Key: owlk_your_key_here" \ "https://api-owlops-public-bugrb4gxeqcghqh5.eastus2-01.azurewebsites.net/v1/vendor/tasks"
Interactive API reference (Swagger): /swagger/index.html
Always use HTTPS. Treat the key like a password: it is not tied to an IP address, so anyone holding it can act as you.
3. What you can see
Two rules apply together, and both must be true:
- The task is assigned to one of your departments. This is what lets one key span every customer — the task belongs to their company, but it is dispatched to yours.
- The key's user is permitted to see that task. A key inherits the permissions of the OwlOps user who created it.
Rule 2 is worth planning around. If you have several departments or crews and want separate integrations, create a key under a user who has access to the right departments — each key then sees only that user's work. If a key is not returning tasks you expect, that is the first thing to check.
Anything outside your scope returns 404, not 403 — we do not reveal whether a task exists on someone else's account.
4. Endpoints
Reading
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/vendor/tasks |
Your assigned tasks, paginated |
GET |
/v1/vendor/tasks/{id} |
A single task |
GET |
/v1/vendor/tasks/{id}/log |
Full activity history |
GET |
/v1/vendor/technicians |
Your users, for assignment |
GET /v1/vendor/tasks accepts these query parameters:
| Parameter | Notes |
|---|---|
status |
Status label, e.g. Open, Hold, Schedule, Closed |
assigned |
true = assigned to one of your technicians, false = unassigned |
technicianUserId |
Tasks for one of your technicians |
customerCompanyId |
Narrow to a single customer |
assetId |
Tasks against a specific asset |
from / to |
Created-date range |
page, pageSize |
pageSize max 250 (100 for the log) |
Writing
Every write returns the updated task, so you do not need to re-fetch it.
| Method | Path | Purpose |
|---|---|---|
POST |
/v1/vendor/tasks/{id}/acknowledge |
Confirm receipt and assign to yourself |
POST |
/v1/vendor/tasks/{id}/assign |
Assign one of your technicians |
POST |
/v1/vendor/tasks/{id}/notes |
Add an update the customer can see |
POST |
/v1/vendor/tasks/{id}/checkin |
On site |
POST |
/v1/vendor/tasks/{id}/checkout |
Leaving site |
POST |
/v1/vendor/tasks/{id}/quote |
Submit a quote (attachment required) |
POST |
/v1/vendor/tasks/{id}/invoice |
Submit an invoice (attachment required) |
POST |
/v1/vendor/tasks/{id}/complete |
Close the task (permission required) |
POST |
/v1/vendor/tasks/{id}/decline |
Decline; may route to another vendor |
POST |
/v1/vendor/tasks/{id}/followup |
Request additional work as a new task |
POST |
/v1/vendor/uploads |
Upload a file to attach |
Every update notifies the customer exactly as it would if your team had entered it in OwlOps directly.
Closing a task depends on the permissions the customer granted you. Each task carries a canClose field — check it before calling complete, or expect a 403. If you should be able to close work for a customer and cannot, that is a setting on their side.
Field limits
| Field | Limit |
|---|---|
notes |
4,000 characters |
quoteNumber, invoiceNumber |
20 characters |
cost |
Greater than 0 |
priorityId |
1–5 (1 Low, 2 Medium, 3 High, 4 Urgent, 5 Non-Urgent) |
5. Attachments
Attaching a file is two steps: upload it, then reference the returned URL.
Step 1 — upload:
curl -X POST -H "X-Api-Key: owlk_your_key_here" \ -F "file=@invoice.pdf" \ "https://api-owlops-public-bugrb4gxeqcghqh5.eastus2-01.azurewebsites.net/v1/vendor/uploads"
{ "url": "https://owlopsstorage.blob.core.windows.net/owlopsstorage/1274/documents/invoice_3f9c1a....pdf", "fileName": "invoice.pdf", "type": "document", "thumbnailUrl": null }
Step 2 — reference that url in a later write, as documentPaths (documents) or imagePaths (images). Separate multiple files with semicolons.
curl -X POST -H "X-Api-Key: owlk_your_key_here" -H "Content-Type: application/json" \ -d '{ "invoiceNumber": "INV-2026-0810", "invoiceDate": "2026-08-10T00:00:00", "cost": 487.50, "notes": "Thermostat assembly plus 1.5h labour", "documentPaths": "https://owlopsstorage.blob.core.windows.net/.../invoice_3f9c1a....pdf" }' \ ".../v1/vendor/tasks/3483497/invoice"
Things to know:
- Only your own uploads can be attached. Paths must be URLs this endpoint returned for your account. Arbitrary or external URLs are rejected with
400. - Quotes and invoices require at least one attachment.
- Limits: 25 MB per file, 10 uploads per minute.
- Accepted types: images (
jpg,jpeg,jpe,png,gif,bmp,webp,heic), documents (pdf,doc,docx,xls,xlsx,txt), video (mp4,mov,webm). - You may upload the same filename repeatedly. Each upload is stored separately, so a second
invoice.pdfnever replaces the first. - Invoice numbers must be unique per customer. Re-using one returns
409.
6. Rate limits
| Limit | Default |
|---|---|
| Requests per minute | 60 |
| Requests per day | 10,000 |
| Uploads per minute | 10 |
Exceeding a limit returns 429 with a Retry-After header in seconds, and retryAfterSeconds in the body. Please honour it rather than retrying immediately.
{ "error": "Rate limit exceeded. Slow down and retry.", "statusCode": 429, "retryAfterSeconds": 60 }
Limits are per key, so your integration is never affected by another vendor's traffic. If your volumes need more, contact support@owlops.com — we can raise your limits without you changing anything.
For now the API is polling only; there are no webhooks. Polling GET /v1/vendor/tasks?status=Open&from=<last check> every few minutes is the intended pattern. Push notifications are on the roadmap — tell us if you want them, as demand will shape the priority.
7. Error responses
| Code | Meaning | What to do |
|---|---|---|
400 |
Invalid request | Read the message; usually a missing field, a value too long, or an attachment path that is not yours |
401 |
Key missing or invalid | Check the X-Api-Key header |
403 |
Wrong key type, or no permission to close | Confirm the key is Vendor type; for complete, check canClose |
404 |
Task does not exist, or is not yours | Do not retry; confirm the task is dispatched to your departments |
409 |
Duplicate invoice number | Use a unique number for that customer |
429 |
Rate limited | Wait for Retry-After |
500 |
Something broke on our side | Note the reference value and send it to support |
Most errors look like this:
{ "error": "Task 568479 not found or not assigned to your company.", "statusCode": 404 }
Field-validation errors are the exception — they come back in the standard problem-details format instead, listing each offending field:
{ "title": "One or more validation errors occurred.", "status": 400, "errors": { "invoiceNumber": ["The field InvoiceNumber must be a string or array type with a maximum length of '20'."] } }
Handle both shapes. Unifying them is on our list for a future release.
A 500 includes a reference value. It is a correlation ID for our logs — quote it to support and we can look up exactly what happened, without you needing to reproduce it.
8. A typical integration
- Poll
GET /v1/vendor/tasks?status=Openfor new work - Acknowledge so the customer knows you have it
- Assign a technician from
GET /v1/vendor/technicians - Check in on arrival, add notes as you work, check out when leaving
- Upload the invoice, then submit it referencing the returned URL
- Complete the task, if the customer has granted you close permission
Steps are independent — use only what fits your process.
9. Beta: current limitations
Known gaps, so they do not surprise you mid-build:
- No webhooks. Polling only.
- Two error formats, as described above.
- No status transition rules. Tasks that are already closed still accept updates.
- Uploaded videos have no preview thumbnail. The file itself is stored and viewable.
- Scheduling is not a dedicated endpoint. Communicate a proposed date through
notes; the customer sets the schedule.
Support
Questions, problems, feature requests, or anything that behaves unexpectedly:
support@owlops.com
If you are reporting a problem, these make it much faster to diagnose:
- the endpoint and HTTP method
- the key prefix (the first 12 characters, e.g.
owlk_wExv8Iq) — never the full key - the status code and response body, including any
referencevalue - roughly when it happened
Because this is beta, we are actively interested in feedback on what is missing or awkward, not only in defects.