API RU
Early access. API keys are issued on request. How to get a key

A successful response always has status 200. An error comes with a 4xx or 5xx status and an RFC 9457 body.

#Format

An error is returned with the Content-Type: application/problem+json header and a body with eight fields:

Error response
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json; charset=utf-8
Request-Id: 0f3c7a95-2e8b-4d16-b9a4-6c5e1d8f7b20
Cache-Control: no-store

{
  "type": "urn:meliora:problem:invalid_parameter",
  "title": "Invalid parameter",
  "status": 400,
  "detail": "Check the parameter value",
  "instance": "urn:request:0f3c7a95-2e8b-4d16-b9a4-6c5e1d8f7b20",
  "code": "invalid_parameter",
  "param": "limit",
  "request_id": "0f3c7a95-2e8b-4d16-b9a4-6c5e1d8f7b20"
}
FieldDescription
typeURI of the error type: urn:meliora:problem: followed by the code.
titleShort name in English.
statusHTTP status, the same as the response status.
detailHuman-readable explanation. The language depends on the Accept-Language header.
instanceURI of the request: urn:request: followed by the request ID.
codeMachine-readable error code.
paramThe parameter the error relates to, or null.
request_idRequest ID, the same as in the Request-Id header.

#Rejections before key validation

Some requests are rejected before the key is validated: the per-IP rate limit is exceeded, the path is unknown, the request has a body, or the service is overloaded. These responses have the same status, code, param and request_id fields, but type is about:blank, and title and detail match code:

JSON
{
  "type": "about:blank",
  "title": "rate_limit_exceeded",
  "status": 429,
  "code": "rate_limit_exceeded",
  "detail": "rate_limit_exceeded",
  "instance": "urn:request:0f3c7a95-2e8b-4d16-b9a4-6c5e1d8f7b20",
  "request_id": "0f3c7a95-2e8b-4d16-b9a4-6c5e1d8f7b20",
  "param": null
}

So rely on status and code, not on type and title.

#Handling errors

  • Branch your logic on status and code. The detail text may change, so don't parse it in code.
  • If you get an unfamiliar code, handle the error by its HTTP status: 4xx means a problem with the request or access, 5xx means a temporary problem on our side.
  • For a parameter error, param contains the parameter name: limit, status, cursor, include_text and so on.
  • An error never advances the cursor. When you retry, a request with the same cursor returns the same data.

#Explanation language

By default, detail is in Russian. To get English text, send the Accept-Language: en header. The code and title fields don't depend on the language.

#Request-Id

Every response, including errors, has a Request-Id header with the request's UUID. Log it together with the endpoint and the time. When you contact Support, the Request-Id is all we need to find the request. Never send us the key itself.

#Error codes

StatusCodeWhat happened
400invalid_parameterThe parameter value has an invalid format, is out of range or is used in an invalid combination. The parameter name is in param.
400unknown_parameterThe route does not accept this parameter. An API key in the URL also causes this error.
400cursor_mismatchThe cursor is corrupted, was issued for a different route or filters, or the key's permissions and scope have changed.
401invalid_api_keyThe key is missing, invalid, revoked or expired.
403scope_requiredThe key does not have permission for this read. Texts also require "Message text" to be enabled.
403api_disabledAPI access is disabled in Meliora.
403api_not_availableThe organization's plan does not include the API. Read access requires Pro or higher.
403subscription_inactiveThe organization's subscription is not active.
403module_not_availableThe outreach module is unavailable for this organization.
403organization_suspendedOrganization access is suspended.
403ip_not_allowedThe request came from an IP address that is not on the key's allow list.
404not_foundThe object was not found or is outside the key's scope. An unknown path also returns 404.
405method_not_allowedOnly the GET method is allowed. The public endpoint answers other methods with a 404 without a body, so this code is not seen from outside.
410cursor_expiredThe cursor expired: 15 minutes for lists, 30 days for the event feed.
429rate_limit_exceededThe request limit of the key, organization or IP address is exhausted. Retry after Retry-After seconds.
503service_unavailableThe data could not be read right now. Retry later.
503server_busyThe service is overloaded. Retry after Retry-After seconds.
503integration_initializingThe new key is still being prepared. Retry later.

#What to retry

StatusRetry?How
400NoFix the parameter named in param. For cursor_mismatch, restart the list.
401, 403NoCheck the key, its permissions and your organization settings.
404NoThe object doesn't exist or is outside the key's scope.
410NoThe cursor expired: restart the list or recover the feed.
429YesWait Retry-After seconds and add random jitter.
503YesWait Retry-After seconds and increase the delay if the error repeats.

For more on delays between retries, see Rate limits and retries.

#Special cases

  • An unknown path or an object ID that isn't a valid UUID returns 404 not_found. Write the path exactly as in the reference: a trailing / or encoded characters in the path also return 404.
  • Methods other than GET, including HEAD and OPTIONS, and URLs outside /v1/ get 404 with no body. You won't see the method_not_allowed code from outside.
  • A body in a GET request, a URL longer than 8 KiB or headers larger than 8 KiB return 400 invalid_parameter with param set to body, uri or headers.
  • A repeated parameter (?status=new&status=replied) and an empty value (?status=) return 400 invalid_parameter.
  • A long-running request is aborted after 10 seconds with 503 service_unavailable.