MOK Integration API (v1)

Download OpenAPI specification:

Integration reference for MOK partners. It covers the Provider Network API (OAuth2) for validating contracts and creating/updating service requests, the webhooks we send for service request events, and the token-authenticated Admin API for loading contracts and point transactions.

Getting started

  1. Request OAuth2 client credentials (client_id / client_secret) and, for the Admin API, an admin user email + token from devs-moklabs@grupomok.com.
  2. Exchange your credentials for a Bearer token at the OAuth2 token endpoint.
  3. Validate a user's contract with GET /api/v1/provider_networks/contracts, then use the returned contract and service ids to create a service request.
  4. Receive status updates on your configured webhook URL (see Webhooks).

Authentication

Provider Network API — OAuth2 Bearer

Send Authorization: Bearer <access_token> on every /api/v1/provider_networks/* request. Tokens are obtained via the client-credentials flow at POST /oauth/token with scope: provider_networks.

Admin API — token headers

The Admin API uses a different audience (sponsor/admin integrators). Send both X-Admin-User-Email and X-Admin-User-Token headers; no OAuth token is required.

Webhooks

Service request events (service_request.created, service_request.updated) are delivered to your configured webhook_url. Each request is signed with an X-Signature HMAC-SHA256 header. See the Webhooks section for payloads and verification.

Changelog

2026-04-29

Contracts
  • Documented the three variable_copayment_* limit types in the limits field (variable_copayment_by_days_of_current_service_request, variable_copayment_by_usage_by_period, variable_copayment_by_accumulated_days_by_period).
  • Added copayment_tiers to the service_limit schema for variable copayment limits.

2025-12-18

Contracts
  • Added limits field to services in the response, containing usage limits information.

2025-12-02

Contracts
  • Added plan_name field to the response.

2025-11-06

Service requests
  • Added access_identifier_kind field to the response.

2025-09-04

Contracts
  • Added external_extra_data field to the response.

2025-08-05

Service requests
  • Added user_email field to the response.
  • Added type (the type of the dynamic form input) to each form answer inside the answers field.

2025-07-21

Contracts
  • Added unique_contract_id, client_contract, and mobile_phone_number fields to the response.

2025-06-18

Service requests
  • Added answers field to the response, it contains the answers from the form if the service has a dynamic form configured.

2025-05-12

Service requests
  • Added user_first_name and user_last_name fields to the response. user_full_name is deprecated and will be removed in the future.
Contracts
  • Added last_name field to the response, it combines surname and second_surname. surname and second_surname may be deprecated in the future so it's recommended to use last_name instead.

Example scenarios

End-to-end examples of how a service request moves through the system — and, most importantly, when your webhook fires.

A request always starts as pending and then moves through assignedstartedfinished (the service was provided), or ends in cancelled (which is final). We send a webhook only for changes that originate on a MOK platform — a member acting in a web app or over WhatsApp. Changes you make yourself through the Provider Network API never send a webhook back to you.

Scenario 1 — Requested on the web, fulfilled by you, provided

A member requests a service in one of our white-labeled web apps. You are notified, fulfill it, and mark it as provided.

sequenceDiagram
    autonumber
    participant U as Member
    participant MOK as MOK platform
    participant P as Your app
    U->>MOK: Requests the service in a MOK web app
    MOK->>MOK: Creates the request (status pending, origin web app)
    MOK->>P: Webhook service_request.created (HMAC signed)
    Note over MOK,P: Fires because the request originated on a MOK platform
    P->>MOK: PATCH status assigned, then started (Provider Network API)
    P->>MOK: PATCH status finished (service provided)
    Note over P,MOK: Your own API updates do not send a webhook back to you

Scenario 2 — Created by you, cancelled by the member

You look up the member's contract by identifier, create a request for them through the API, and later the member cancels it — which you find out about through a webhook.

sequenceDiagram
    autonumber
    participant P as Your app
    participant MOK as MOK platform
    participant U as Member
    P->>MOK: GET /contracts by access_identifier (Provider Network API)
    MOK-->>P: Matching contract with its available services
    Note over P,MOK: Use the returned contract id and service id to create the request
    P->>MOK: POST /service_requests (Provider Network API)
    MOK->>MOK: Creates the request (status pending, origin api)
    Note over P,MOK: No webhook is sent, because you created it yourself
    U->>MOK: Cancels the request from a MOK web app or WhatsApp
    MOK->>MOK: Status becomes cancelled (final, origin web app)
    MOK->>P: Webhook service_request.updated (status cancelled)
    Note over MOK,P: Fires because the member, not you, made the change

What the contract lookup returns

GET /api/v1/provider_networks/contracts (the first step above) is how you validate a member before creating a request. Each contract in the response carries the member's details (name, contact, start_date / end_date, active, plan) and a services array. Every service includes an id and an optional external_idthese are the ids you pass back when creating the request.

When you look a member up by access_identifier (or the deprecated document_identifier), each service also carries a limits object describing what that member may still use. It is omitted for lookups by email, national ID, or internal id, and for services that have no limits configured. The limit types fall into a few families:

  • Usage frequency (by end of contract, or per period) — maximum number of uses.
  • Max cost (by end of contract, per period, or per use) — maximum spend.
  • Waiting period — the member must wait before their first use (shown only while it is still blocking).
  • Copayment — a flat amount the member pays.
  • Variable copayment (by request days, usage per period, or accumulated days) — the copayment varies by copayment_tiers.

Read a single limit with: multiplans_limit (the cap), multiplans_limit_progress (consumed so far), multiplans_until_date (dd/mm/yyyy), and copayment_tiers (variable-copayment limits only). Two quick checks live on the service: has_any_limits (are any limits configured), and, at the root of the limits object, block_servicetrue means the member cannot use this service right now.

For the full field-by-field breakdown of every limit type, see the Contracts endpoint.

Scenario 3 — A request blocked by a limit

The member has already used up an allowance (say, all their uses for the period). The contract lookup tells you up front, and a create attempted anyway is rejected.

sequenceDiagram
    autonumber
    participant P as Your app
    participant MOK as MOK platform
    P->>MOK: GET /contracts by access_identifier
    MOK-->>P: Contract, with the service flagged block_service true
    Note over P,MOK: The member has reached a limit (e.g. all uses in the period)
    P->>MOK: POST /service_requests for that service
    MOK-->>P: 403 Forbidden, service limit exceeded
    Note over P,MOK: Check block_service before creating to avoid the rejection

Before creating a request, check the service's block_service flag (and, if you want detail, compare multiplans_limit_progress against multiplans_limit) from the contract lookup. Creating a request for a member who is over their limit is rejected with 403 Forbidden (service limit exceeded).

Authentication

Obtain an access token

OAuth2 endpoint to obtain an access token using client credentials flow. The access token must be included in all subsequent API requests in the Authorization header.

Example:

Authorization: Bearer your_access_token

Flow

sequenceDiagram
    autonumber
    participant C as Your app
    participant A as Authorization server
    participant API as Provider Network API
    C->>A: POST /oauth/token (grant_type=client_credentials, scope=provider_networks)
    A->>A: Validate client_id and client_secret
    A-->>C: 200 with access_token, token_type Bearer, expires_in
    Note over C: Reuse the token until it expires
    C->>API: GET a provider_networks endpoint with header Authorization Bearer token
    API-->>C: 200 resource
Request Body schema: application/json
grant_type
required
string
client_id
required
string
client_secret
required
string
scope
required
string

Responses

Request samples

Content type
application/json
{
  • "grant_type": "client_credentials",
  • "client_id": "109fb51a-ba5a-49d7-92e6-89fc67a63e9f",
  • "client_secret": "v1OINpq6T",
  • "scope": "provider_networks"
}

Response samples

Content type
application/json
{
  • "access_token": "YOUR_ACCESS_TOKEN_HERE",
  • "token_type": "Bearer",
  • "scope": "provider_networks",
  • "created_at": 1777889583
}

Provider Networks

Get provider network info and webhook URL

Retrieves information about the authenticated provider network, including their services that are present in this specific application, and your configured webhook_url.

Webhook Notifications

Service request events are delivered to your configured webhook_url. Rendered API docs also show each event as a dedicated Webhooks entry with its full payload schema.

Events

  • service_request.created: a service request was created from one of our platforms.
  • service_request.updated: a service request was updated from one of our platforms.

Payload

{
  "event": "service_request.created",
  "payload": { ...service request (see the Service Requests schema for all fields) }
}

Security

Each request includes an X-Signature header: an HMAC-SHA256 hex digest of the raw request body, keyed with your webhook_secret. A Webhook-From header carries the sending host. Verify the signature before trusting the payload:

signature = request.headers['X-Signature']
expected  = OpenSSL::HMAC.hexdigest('SHA256', webhook_secret, request.raw_post)
valid     = ActiveSupport::SecurityUtils.secure_compare(signature, expected)

Authentication (optional, configured per provider network)

Requests may also carry credentials via HTTP Basic, a static Bearer token, or a Bearer token fetched from a configured auth URL. Contact us to set or change your webhook_url, secret, or auth mode.

Authorizations:
Bearer

Responses

Response samples

Content type
application/json
{
  • "provider_network": {
    }
}

Contracts

Retrieves contracts for a document identifier, national ID, email, ID or access identifier

Returns a list of contracts associated with the provided document identifier (DNI, mobile phone number, or access code), national ID, email, ID or access identifier. Each contract includes the customer's personal information, contract dates, and available services so you can validate them before creating a service request.

Important: The contract id and service id returned in this response are required to create a service request.

Important

  • The document_identifier field is deprecated and will be removed in the future.
  • The access_identifier field is the new field that will be used to identify the contract.

Service Limits

Each service includes a limits object that describes usage restrictions for the user. The limits field is only present when searching by access_identifier or document_identifier.

Limit Types

  • usage_frequency_by_end_of_contract: Maximum number of uses allowed until the contract ends.
  • usage_frequency_by_period: Maximum number of uses allowed per period (e.g., monthly).
  • waiting_period: Time the user must wait before using the service.
  • max_cost_by_end_of_contract: Maximum cost allowed until the contract ends.
  • max_cost_by_period: Maximum cost allowed per period.
  • max_cost_by_use: Maximum cost allowed per single use.
  • copayment: Copayment amount required for the service.
  • variable_copayment_by_days_of_current_service_request: Copayment that varies based on the number of days of the current service request, defined by tiers.
  • variable_copayment_by_usage_by_period: Copayment that varies based on usage within a period, defined by tiers.
  • variable_copayment_by_accumulated_days_by_period: Copayment that varies based on accumulated days within a period, defined by tiers.

Interpreting Limit Values

  • multiplans_limit: The maximum allowed value (uses or cost).
  • multiplans_limit_progress: Current usage towards the limit.
  • block_service: If true, the user cannot use this service (limit exceeded or waiting period active).
  • multiplans_until_date: Date until which the limit applies (format: dd/mm/yyyy).
  • copayment_tiers: Array of tiers describing the copayment structure for variable copayment limits. Only present for variable_copayment_* limit types.

Quick Check

  • Use has_any_limits to check if any limits are configured for the service.
  • Use block_service (at the root level) to check if the service is blocked due to any limit.
Authorizations:
Bearer
query Parameters
document_identifier
string

Document identifier to search contracts for. Can be one of:

  • DNI/National ID (e.g. "12345678-9")
  • Mobile phone number with or without country code, the country code will be automatically added if missing.
  • Access code (e.g. "123456")
access_identifier
string

Access identifier to search contracts for. Can be one of:

  • DNI/National ID (e.g. "12345678-9")
  • Mobile phone number with or without country code, the country code will be automatically added if missing. (e.g. "1234567890")
  • Access code (e.g. "123456")
national_id
string

National ID used to search for contracts

id
string

ID used to search for contracts

email
string

Email used to search for contracts

Responses

Response samples

Content type
application/json
{
  • "contracts": [
    ]
}

Plans

Retrieves plans

Returns a list of plans. Only services owned by the logged in provider network are included in each plan.

Authorizations:
Bearer

Responses

Response samples

Content type
application/json
{
  • "plans": [
    ]
}

Service Requests

Get all service requests

Retrieves all service requests associated with the logged in provider network.

Important

  • The document_identifier field is deprecated and will be removed in the future.
  • The access_identifier field is the new field that will be used to identify the contract.
  • The access_identifier_kind field is the kind of the access identifier. It can be national_id, mobile_phone_number, email, phone_number or access_code.
Authorizations:
Bearer
query Parameters
current_status
string

Filter service requests by current status

service_id
integer

Filter service requests by service ID

contract_id
integer

Filter service requests by contract ID

external_id
string

Filter service requests by your external ID

access_identifier
string

Filter service requests by User access identifier

document_identifier
string

Filter service requests by User document identifier

service_external_id
string

Filter service requests by service external ID

page[number]
integer
Default: 1

Page number

page[size]
integer
Default: 25

Number of results per page

Responses

Response samples

Content type
application/json
{
  • "service_requests": [
    ]
}

Create a new service request

Creates a new service request for a user. This endpoint allows creating service requests for contracts that were previously validated using the contracts endpoint or by providing a document identifier or access identifier that matches an existing contract.

Important:

  • A valid service is required and must be provided either by including the service_id parameter or by providing a service_external_id that matches an existing service's external ID.
  • If both service_id and service_external_id are provided, the service_external_id will have priority.
  • A valid contract is required and must be provided either by including the contract_id or by providing a access_identifier or document_identifier that matches an existing contract.
  • The external_id is an optional field that can be used to link the service request to your internal reference ID.

Important

  • The document_identifier field is deprecated and will be removed in the future.
  • The access_identifier field is the new field that will be used to identify the contract.

Accepted fields

service_id, contract_id, external_id, current_status, access_identifier, requested_at, service_name, origin_address, origin_latitude, origin_longitude, destination_address, destination_latitude, destination_longitude, scheduled_date, scheduled_end_date, scheduled_time, provider_name, provider_phone, technician_name, user_phone, source, contact_center_phone, service_external_id

Flow

sequenceDiagram
    autonumber
    participant C as Your app
    participant API as Provider Network API
    C->>API: POST /service_requests with header Authorization Bearer token
    API->>API: Resolve the service and validate the request
    API-->>C: 201 service_request
    Note over C,API: Requests you create through the API do not send a webhook back to you
Authorizations:
Bearer
Request Body schema: application/json
object

Responses

Request samples

Content type
application/json
Example
{
  • "service_request": {
    }
}

Response samples

Content type
application/json
{
  • "service_request": {
    }
}

Get a service request

Retrieves a specific service request by its ID.

Authorizations:
Bearer
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "service_request": {
    }
}

Update a service request

Updates an existing service request. This endpoint allows updating certain fields of a service request after it has been created.

Important:

  • Some fields like service_id and contract_id cannot be modified after creation

Important

  • The document_identifier field is deprecated and will be removed in the future.
  • The access_identifier field is the new field that will be used to identify the contract.

Accepted fields

external_id, current_status, service_name, origin_address, origin_latitude, origin_longitude, destination_address, destination_latitude, destination_longitude, scheduled_date, scheduled_end_date, scheduled_time, provider_name, provider_phone, technician_name, user_phone, contact_center_phone

Flow

sequenceDiagram
    autonumber
    participant C as Your app
    participant API as Provider Network API
    C->>API: PATCH /service_requests/{id} with header Authorization Bearer token
    API->>API: Apply the update
    API-->>C: 200 service_request
Authorizations:
Bearer
path Parameters
id
required
integer
Request Body schema: application/json
object

Responses

Request samples

Content type
application/json
{
  • "service_request": {
    }
}

Response samples

Content type
application/json
{
  • "service_request": {
    }
}

WhatsApp

Request WhatsApp message sending

Receives a request to send a WhatsApp message.

The whatsapp_number parameter is required.

The whatsapp_number must be a valid number according to the E.164 standard.

Flow

sequenceDiagram
    autonumber
    participant C as Your app
    participant API as Provider Network API
    participant WA as WhatsApp provider
    participant U as End user
    C->>API: POST /whatsapp/send with a whatsapp_number
    API->>API: Normalize and validate the E.164 number
    API->>WA: Send the opening WhatsApp message
    WA->>U: Message delivered to the end user's phone
    API-->>C: 200 message sent successfully
Authorizations:
Bearer
Request Body schema: application/json
whatsapp_number
required
string

WhatsApp number of the user who called the call center

Responses

Request samples

Content type
application/json
{
  • "whatsapp_number": "123456789"
}

Response samples

Content type
application/json
null

Webhooks

service_request.created Webhook

Sent to your configured webhook_url whenever a service request is created from one of our platforms. Your endpoint should respond with a 2xx status to acknowledge receipt; non-2xx responses are retried with exponential backoff.

Security

Every request includes an X-Signature header: an HMAC-SHA256 hex digest of the raw request body, keyed with your webhook_secret. Verify it before trusting the payload:

signature = request.headers['X-Signature']
expected  = OpenSSL::HMAC.hexdigest('SHA256', webhook_secret, request.raw_post)
valid     = ActiveSupport::SecurityUtils.secure_compare(signature, expected)

Authentication (optional, configured per provider network)

In addition to the signature, requests may carry credentials in one of these modes:

  • Basic — HTTP Basic Authorization header with your username/password.
  • Bearer (static) — a fixed bearer token that does not expire.
  • Bearer (fetched) — we POST your username/password to a configured auth URL and use the returned token. The JSON keys for username, password and token are configurable.

To change your webhook_url, webhook_secret, or auth mode, contact us at devs-moklabs@grupomok.com.

Flow

sequenceDiagram
    autonumber
    participant P as MOK platform (web app)
    participant MOK as Provider Network API
    participant Q as Background worker
    participant W as Your webhook_url
    P->>MOK: A service request is created or updated on a MOK platform
    MOK->>Q: Enqueue webhook delivery job
    Q->>W: POST event and payload with headers X-Signature and Webhook-From
    W->>W: Compute HMAC-SHA256 of the raw body keyed with webhook_secret
    W->>W: Compare the result against the X-Signature header
    alt signature valid
        W-->>Q: 2xx acknowledge
    else invalid or processing error
        W-->>Q: non-2xx
        Note over Q,W: Delivery is retried with exponential backoff
    end
Authorizations:
Bearer
header Parameters
X-Signature
string

HMAC-SHA256 hex digest of the raw request body, keyed with your webhook_secret.

Webhook-From
string

The application host that sent the webhook.

Request Body schema: application/json
event
required
string
Enum: "service_request.created" "service_request.updated"

The event that triggered the webhook.

required
object (service_request)

Responses

Request samples

Content type
application/json
{
  • "event": "service_request.created",
  • "payload": {
    }
}

service_request.updated Webhook

Sent to your configured webhook_url whenever a service request is updated from one of our platforms (for example, a status change). The signature, authentication and acknowledgement rules are identical to service_request.created above.

Authorizations:
Bearer
header Parameters
X-Signature
string

HMAC-SHA256 hex digest of the raw request body, keyed with your webhook_secret.

Webhook-From
string

The application host that sent the webhook.

Request Body schema: application/json
event
required
string
Enum: "service_request.created" "service_request.updated"

The event that triggered the webhook.

required
object (service_request)

Responses

Request samples

Content type
application/json
{
  • "event": "service_request.updated",
  • "payload": {
    }
}

Admin · Contracts

List contracts

Returns every contract known to the application.

Authorizations:
(AdminUserEmailAdminUserToken)

Responses

Response samples

Content type
application/json
{
  • "contracts": [
    ]
}

Create or update a contract

Creates a contract, or updates the active contract that matches the given application_code (plan code) and access_identifier. When an active contract exists with a different client_contract, a new contract is created instead of updating the existing one.

The response new_contract? flag tells you whether a contract was created or updated, and success? / errors report validation results.

Authorizations:
(AdminUserEmailAdminUserToken)
Request Body schema: application/json
required
object

Responses

Request samples

Content type
application/json
{
  • "contract": {
    }
}

Response samples

Content type
application/json
{
  • "contract": {
    }
}

Batch create or update contracts

Creates or updates many contracts in a single request. Each item follows the same rules as create_or_update. The response returns one contract object per item, each carrying its own success? / errors, so partial failures can be inspected without failing the whole batch.

Authorizations:
(AdminUserEmailAdminUserToken)
Request Body schema: application/json
required
Array of objects

Responses

Request samples

Content type
application/json
{
  • "contracts": [
    ]
}

Response samples

Content type
application/json
{
  • "contracts": [
    ]
}

Admin · Point Transactions

List point transactions

Returns every point transaction.

Authorizations:
(AdminUserEmailAdminUserToken)

Responses

Response samples

Content type
application/json
{
  • "point_transactions": [
    ]
}

Create a point transaction

Adds or spends points for the user identified by access_identifier. The transaction is processed asynchronously.

Authorizations:
(AdminUserEmailAdminUserToken)
Request Body schema: application/json
required
object

Responses

Request samples

Content type
application/json
{
  • "point_transaction": {
    }
}

Response samples

Content type
application/json
{
  • "point_transaction": {
    }
}

Get a point transaction

Authorizations:
(AdminUserEmailAdminUserToken)
path Parameters
id
required
integer

Point transaction ID

Responses

Response samples

Content type
application/json
{
  • "point_transaction": {
    }
}

Admin · Recurrent Point Transactions

List recurrent point transactions

Authorizations:
(AdminUserEmailAdminUserToken)

Responses

Response samples

Content type
application/json
{
  • "recurrent_point_transactions": [
    ]
}

Create a recurrent point transaction

Schedules a rule that issues point transactions on a recurring cadence defined by recurrence_period (an ISO 8601 duration such as P1D or P1M).

Authorizations:
(AdminUserEmailAdminUserToken)
Request Body schema: application/json
required
object

Responses

Request samples

Content type
application/json
{
  • "recurrent_point_transaction": {
    }
}

Response samples

Content type
application/json
{
  • "recurrent_point_transaction": {
    }
}

Get a recurrent point transaction

Authorizations:
(AdminUserEmailAdminUserToken)
path Parameters
id
required
integer

Recurrent point transaction ID

Responses

Response samples

Content type
application/json
{
  • "recurrent_point_transaction": {
    }
}

Update a recurrent point transaction

Authorizations:
(AdminUserEmailAdminUserToken)
path Parameters
id
required
integer

Recurrent point transaction ID

Request Body schema: application/json
required
object

Responses

Request samples

Content type
application/json
{
  • "recurrent_point_transaction": {
    }
}

Response samples

Content type
application/json
{
  • "recurrent_point_transaction": {
    }
}

Delete a recurrent point transaction

Authorizations:
(AdminUserEmailAdminUserToken)
path Parameters
id
required
integer

Recurrent point transaction ID

Responses

Provider Ranking

Get provider ranking for a zone and service

Returns the providers ranked for a given zone and service, scoped to the authenticated provider network.

Both zone_external_id and service_external_id are required; omitting either returns a 422 with detail missing_required_params.

Flow

sequenceDiagram
    autonumber
    participant C as Your app
    participant M as mok-services
    Note over C,M: Served from the central host mokservices.moklabs.com, not your per-sponsor host
    C->>M: GET /providers/ranking with zone_external_id and service_external_id
    M->>M: Rank the providers for that zone and service
    M-->>C: 200 with a providers list (position, provider_name, external_id)
Authorizations:
Bearer
query Parameters
zone_external_id
required
string

External ID of the zone to rank providers for.

service_external_id
required
string

External ID of the service to rank providers for.

Responses

Response samples

Content type
application/json
{
  • "providers": [
    ]
}