Authentication
A company administrator creates an integration in the application, grants it authorized data by domain and field group, and creates a client. There are two ways to authenticate requests; both are sent as Authorization: Bearer.
OAuth 2.0, client credentials (recommended)
POST https://daas.masnet.com/api/v1/integrations/oauth/token with Content-Type: application/x-www-form-urlencoded. The client authenticates with client_secret_basic (Authorization: Basic) or with client_id and client_secret in the body, but not both at once. The client_id has the form mkc_ followed by 24 hexadecimal characters and the secret mks_ followed by 43 characters. Only grant_type=client_credentials is supported.
POST /api/v1/integrations/oauth/token HTTP/1.1
Host: daas.masnet.com
Authorization: Basic <base64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&scope=read:contracts%20read:guarantees{
"access_token": "<jwt>",
"token_type": "Bearer",
"expires_in": 900,
"scope": "read:contracts read:guarantees"
}- The token is a 15-minute JWT. There are no refresh tokens: request a new one when it expires.
scopeis optional. The granted scope is the intersection between what you request and the data authorized for the integration; if the intersection is empty, the response is400 invalid_scope.- Errors at this endpoint follow RFC 6749:
{ "error": "...", "error_description": "..." }. An invalid or revoked client responds401 invalid_clientwithWWW-Authenticate: Basic realm="masnet-integrations", without distinguishing the cause. - The endpoint accepts 60 requests per minute per IP address and, after repeated failures, temporarily blocks that address (
429withRetry-After). - RFC 8414 metadata is at
/.well-known/oauth-authorization-serverand the public keys that verify the tokens at/jwks.json, both under the same base.
API key
For tools without OAuth: Authorization: Bearer mk_live_… in a production integration or mk_test_… in a test one. The value is shown only once at creation. By default it expires after 365 days.
Scopes and authorized data
A scope enables a domain, but the fields returned depend on the granted groups (public, business, confidential, people). Revoking the permission makes the API respond 403 immediately.
| Family | Scopes |
|---|---|
| Read | read:opportunities, read:tenders, read:bids, read:awards, read:contracts, read:guarantees, read:deadlines, read:documents, read:catalog, read:prices, read:exports, read:events, read:audit |
| Write | write:catalog, write:prices. Only the catalog and price rules accept writes; writing implies being able to read the same domain. |
read:events enables the events log; read:audit the user actions log, which also requires a declaration by the company administrator.
Resources
Each resource is read with GET on the collection and GET …/{id} on the item. Purchase orders and milestones belong to the contracts domain.
| Collection | Scope | Filters |
|---|---|---|
https://daas.masnet.com/api/v1/integrations/data/bids | read:bids | tender_code, status (draft, ready, submitting, portal_draft, submitted, failed, portal_deleted, abandoned), include_deleted |
https://daas.masnet.com/api/v1/integrations/data/awards | read:awards | tender_code, state (detected, confirmed, dismissed) |
https://daas.masnet.com/api/v1/integrations/data/contracts | read:contracts | contract_code, tender_code, buyer_rut, status, ends_before, ends_after |
https://daas.masnet.com/api/v1/integrations/data/purchase-orders | read:contracts | po_code, contract_id, link_state (suggested, confirmed, rejected) |
https://daas.masnet.com/api/v1/integrations/data/guarantees | read:guarantees | status, expires_before, expires_after, tender_code, issuer_id, include_deleted |
https://daas.masnet.com/api/v1/integrations/data/opportunities | read:opportunities | tender_code, stage, decision (go, no_go, defer), business_line_id, include_deleted |
https://daas.masnet.com/api/v1/integrations/data/milestones | read:contracts | contract_id, type, status, planned_before, planned_after, include_deleted |
https://daas.masnet.com/api/v1/integrations/data/deadlines | read:deadlines | entity_id, kind, status (scheduled, done, cancelled, not_applicable), due_before, due_after |
https://daas.masnet.com/api/v1/integrations/data/catalog-items | read:catalog | is_active (true, false), internal_code |
https://daas.masnet.com/api/v1/integrations/data/price-rules | read:prices | catalog_id, is_active (true, false) |
All collections accept limit, cursor and updated_since (RFC 3339 date). An unknown parameter is rejected with 400 invalid_parameter: the company is never a parameter, it is derived from the credential. Identifiers are UUIDs, except the catalog and price rules, which use decimal integers as text. An object of another company or a nonexistent one responds 404.
Returned objects have the same shape as data.object of events; see the schemas.
Pagination and conditional reads
limit: 100 by default, maximum 500.- The response is
{ "data": […], "next_cursor": "…" | null, "has_more": true | false }. To continue, repeat the request withcursor=<next_cursor>and the same filters. - The cursor is opaque, valid for 24 hours and works only with the filters it was issued for; another filter responds
400, an expired one410 cursor_expired. If the data permission changes mid-traversal, it responds410 cursor_scope_changed: restart the traversal. A permission change does not mean objects were deleted. - Deletions: resources with soft deletion (bids, guarantees, opportunities and milestones) are omitted by default; with
include_deleted=truethey appear withdeleted_at. Reading a deleted object by identifier responds410 gonewithdeleted_atfor 30 days; afterwards,404. - Single reads: the response includes
ETag; send it back inIf-None-Matchto receive304if it did not change.
Initial load and synchronization
- Note the time of the first event you receive by webhook.
- Traverse each collection without
updated_sinceuntilhas_moreisfalse. - Apply the events with a
sequencegreater than the version you loaded.
Events log
GET https://daas.masnet.com/api/v1/integrations/data/events with the read:events scope returns the envelopes of the last 30 days, newest first, with the same format and field groups as webhooks and only for the authorized domains. It serves to reconcile after an outage or for a middleware without a public endpoint.
typeandsubject(exact filters),sinceanduntil(RFC 3339),limitandcursor.limit: 50 by default, maximum 200. Response:data,next_cursorandhas_more.- A cursor older than the retention responds
410 cursor_expired: reload with the data API. A malformed cursor responds400 invalid_cursor. - An event is obtained with
GET …/data/events/{id}; a foreign or unauthorized event responds404. A body that does not fit in a list is omitted from it.
User actions log
GET https://daas.masnet.com/api/v1/integrations/data/audit/actions with read:audit returns batches of the actions log by numeric cursor. It requires the administrator to declare that the company informed its users of the monitoring; without it, it responds 403 audit_declaration_required. Parameters: after_seq, limit (1 to 50, 50 by default), since, until, actor, channel, action, origin and result. Name, email, IP and user agent are returned only with the people group.
Catalog operations and exports
With write:catalog or write:prices the integration can apply changes to the catalog through operations: POST https://daas.masnet.com/api/v1/integrations/data/catalog-operations creates an operation, GET …/catalog-operations/{id} and …/results query it, and POST …/{id}/validate, …/apply and …/cancel govern it. POST …/catalog-exports requests an export and GET …/catalog-exports/{id}/items reads it. The required scope depends on the fields each operation touches; an operation from a test integration can be validated, but only a production one applies it. Idempotency uses client_request_id (UUID). The body contract (catalog-exchange.v1) is published by the catalog module and is not reproduced on this page.
Quotas
| Scope | Quota |
|---|---|
| Reads per client | 600 requests per minute |
| Writes per client (operations and exports) | 60 per minute, in addition to the read quota |
| Token endpoint | 60 per minute per IP address |
When exceeded, the API responds 429 rate_limited with Retry-After: 60 and the IETF draft 7 RateLimit headers. No response of this API is stored in caches (Cache-Control: no-store).
Errors
Errors use application/problem+json (RFC 9457) with the members type, title, status, detail, code and correlation_id. The type is a documented URL under Errors, for example https://masnet.com/developers/errors/insufficient_scope. Quote the correlation_id when contacting support. detail never includes database messages, internal identifiers or data of another company.
{
"type": "https://masnet.com/developers/errors/insufficient_scope",
"title": "Alcance insuficiente",
"status": 403,
"detail": "La credencial no tiene el scope read:contracts sobre datos autorizados.",
"code": "insufficient_scope",
"correlation_id": "<identifier>"
}