Overview
The PayTraq Billing API is a web service that is available over HTTPS by using the following endpoint: https://go.paytraq.com/api/billing
This API can be used by a custom billing solution purposely for bulk invoice generation.
All invoice data is collected externally and provided in the generation request.
For other use cases please look at our core API.
Requests and Responses
All API requests and responses must be transmitted over HTTPS.
The API supports the following HTTP methods: GET and POST.
All POST requests must:
- send the request body in JSON format;
- include the following header:
Content-Type: application/jsonUnless otherwise specified, successful responses are returned in JSON format.
Authentication
Depending on the type of integration, the API supports two authentication methods.
For Public Integrations it is also required to specify the company context.
Private Integrations
Private integrations are developed and maintained by the business itself.
To get started, the primary user must generate API credentials for the company profile.
This can be done from My Paytraq -> API Access section.
API credentials consist of an API Key and an API Token, which must be included in every API request for authentication and authorization.
The APIKey and APIToken can be supplied either:
- as HTTP request headers; or
- as query string parameters.
curl -v https://go.paytraq.com/api/{APICall} \
-H "Content-Type:application/xml" \
-H "APIToken:{APIToken}" \
-H "APIKey:{APIKey}" \
-d "{RequestBody}"curl -v https://go.paytraq.com/api/{APICall}?APIToken={APIToken}&APIKey={APIKey} \
-H "Content-Type:application/xml" \
-d "{RequestBody}"API credentials can be regenerated at any time. Regenerating the credentials immediately invalidates the previous API Key/Token pair. API access can also be revoked at any time by deleting the active credentials.
Public Integrations (Third-Party Providers)
Public integrations use OAuth 2.1 and short-lived access tokens for authentication.
https://go.paytraq.com/oauthhttps://go.paytraq.com/.well-known/oauth-authorization-server/oauthThe following OAuth grant types are supported.
Client Credentials Grant
The Client Credentials grant is intended for server-to-server integrations.
Before requesting an access token, an application must be registered to obtain a client_id and client_secret.
This can be done by a Paytraq user from My Paytraq -> Integrations section.
These credentials are then exchanged for an access token.
curl -s https://go.paytraq.com/oauth/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d grant_type=client_credentials \
-d client_id=CLIENT_ID \
-d client_secret=CLIENT_SECRETResponse
{
"access_token": ACCESS_TOKEN,
"token_type": "Bearer",
"expires_in": 86399,
"scope": ""
}The access token must be included in every API request using the following HTTP header:
Authorization: Bearer ACCESS_TOKENAuthorization Code Grant (PKCE)
The Authorization Code grant is intended for applications acting on behalf of a user and follows the OAuth 2.1 Authorization Code flow with PKCE.
Before initiating the authorization flow, an application must be registered to obtain a client_id.
For security reasons, callback URLs used during dynamic client registration must be whitelisted. If you are developing a new third-party integration, you must contact us and request that your callback URL be added to the whitelist before attempting dynamic client registration.
curl -s https://go.paytraq.com/oauth/register \
-H 'Content-Type: application/json' \
-d '{
"client_name": "Client Application Name",
"redirect_uris": ["http://localhost:8080/callback"],
"scope": "api"
}'Response
{
"client_id": "GjAtdC5s7gUXMSEXe0PpZLgc_xNYHD09",
"client_id_issued_at": 1784645567,
"client_name": "Client Application Name",
"redirect_uris": [
"http://localhost:8080/callback"
],
"grant_types": [
"authorization_code",
"refresh_token"
],
"response_types": [
"code"
],
"token_endpoint_auth_method": "none",
"scope": "api"
}The application redirects the user to the authorization endpoint, where the user authenticates and grants consent.
CHALLENGE is a base64url-encoded SHA256 hash of the VERIFIER string, which is a random string generated by the application.
https://go.paytraq.com/oauth/authorize?response_type=code
&client_id=CLIENT_ID
&redirect_uri=REDIRECT_URI
&scope=api
&code_challenge=CHALLENGE
&code_challenge_method=S256
&resource=https://go.paytraq.com/api
&state=abc123Response
REDIRECT_URI?code=AUTHORIZATION_CODE&state=abc123After successful authorization, the application receives an authorization code, which can be exchanged for an access token and a refresh token.
Authorization code is valid for 5 minutes and can only be used once.
VERIFIER is the original random string used to generate the code challenge.
curl -s https://go.paytraq.com/oauth/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d grant_type=authorization_code \
-d client_id=CLIENT_ID \
-d redirect_uri=REDIRECT_URI \
-d code=AUTHORIZATION_CODE \
-d code_verifier=VERIFIERResponse
{
"access_token": ACCESS_TOKEN,
"token_type": "Bearer",
"expires_in": 86399,
"scope": "api",
"refresh_token": REFRESH_TOKEN
}When the access token expires, the refresh token can be used to obtain a new access token without requiring the user to authenticate again.
Refresh token is valid for 30 days and can only be used once.
curl -s https://go.paytraq.com/oauth/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d grant_type=refresh_token \
-d client_id=CLIENT_ID \
-d refresh_token=REFRESH_TOKEN \
-d scope=apiResponse
{
"access_token": ACCESS_TOKEN,
"token_type": "Bearer",
"expires_in": 86399,
"scope": "api",
"refresh_token": REFRESH_TOKEN
}The access token must be included in every API request using the following HTTP header:
Authorization: Bearer ACCESS_TOKENCompany Context
Every API request authenticated with an OAuth access token must also specify the target company (tenant) by including the CompanyID header.
CompanyID: COMPANY_IDTo retrieve the list of companies available to the authenticated user or application, call:
GET /api/billing/companiesResponse
{
"companies": [
{
"company_id": _company_id,
"company_name": _company_name
}
]
}List of Return Codes and Statuses
| Code | Status | Definition |
|---|---|---|
| 200 | OK | The request has succeeded. |
| 400 | Bad Request | The request could not be understood by the server due to malformed syntax, invalid values or validation issues. |
| 401 | Unauthorized | API credentials have not been provided or company license key is not valid. |
| 403 | Forbidden | Request is not permitted and has been forbidden by the server due to incorrect data, validation issues or authorization failure. |
| 404 | Not Found | The server has not found anything matching the Request-URI. |
| 429 | Too Many Requests | The user has sent too many requests in a given amount of time ("rate limiting"). |
| 500 | Internal Server Error | The server encountered an unexpected condition which prevented it from fulfilling the request. |
| 501 | Not Implemented | The method called has not been implemented yet. |
| 503 | Service Unavailable | The server is currently unable to handle the request due to maintenance of the server. This is a temporary condition which will be alleviated after some delay. |
API Convensions
- Decimal values should be passed with dot separator e.g. 10.90
- Dates should be passed in the following format YYYY-MM-DD e.g. 2014-01-30
- Boolean values should be false or true, 0 or 1 is not permitted.
API Limits
- API Rate Limit: 1 request per second at an average, with bursts not exceeding 5 requests
-
The daily API limit is 5000 requests per 24 hours.
If you intend to make additional requests, please reach out to us beforehand by providing a description of your use case (Additional fees may apply).
Excessive API usage may lead to the disabling of API access.
API Calls
POSTStarting of Billing Process for Invoice Generation
Request
POST /api/billing/runPayload
{
"billing": {
"webhook_url": _webhook_url,
"period": _period,
"invoice_date": _invoice_date,
"tax_inclusive": _tax_inclusive,
"invoices": [
{
"client": {
"client_correlation_id": _client_correlation_id,
"client_id": _client_id,
"client_name": _client_name,
"client_email": _client_email,
"client_phone": _client_phone,
"client_details": _client_details,
"client_reg_number": _client_reg_number,
"client_vat_number": _client_vat_number,
"client_contract": _client_contract,
"client_project_name": _client_project_name,
"client_group_name": _client_group_name,
"is_company": _is_company,
"send_to": _is_send_to,
"billing_address": {
"address": _address,
"zip": _zip,
"country_code": _country_code
}
},
"invoice_ref": _invoice_ref,
"invoice_correlation_id": _invoice_correlation_id,
"custom_data": [
{
"field_name": _field_name,
"field_value": _field_value
}
],
"comment": _comment,
"items": [
{
"item_code": _item_code,
"item_name": _item_name,
"item_qty": _item_qty,
"item_uom": _item_uom,
"item_price": _item_price,
"item_tax_rate": _item_tax_rate,
"item_tax_name": _item_tax_name,
"item_discount": _item_discount,
"item_description": _item_description,
"item_account_code": _item_account_code,
"item_period": _item_period
}
],
"payment": {
"money_account_id": _money_account_id,
"date_paid": _date_paid
},
"footer": _footer
}
]
}
}Based on this request, synchronisation of clients, services and units of measurement occurs, as well as generation and distribution of invoices.
| Tag | Description |
|---|---|
| webhook_url | URL to which a notification about the end of the generation process will be sent (Optional) |
| period | Billing period (Optional)
1 - current month 2 - previous month 3 - next month |
| invoice_date | Invoice date, if not specified, then the current one. Format - YYYY-MM-DD |
| tax_inclusive | Boolean value (true or false). If true then unit prices are tax inclusive. Default is true. |
| invoice_ref | Invoice Number in PayTraq (Optional) |
| invoice_correlation_id | Invoice ID from external system. Can be used for data mapping on the client's side (Optional) |
| custom_data | Custom fields, if a field name is not found, then it will created (Optional) |
| comment | Comment added to the invoice (Optional) |
| footer | Html footer in base64 encoding. It will be added to the end of the PDF invoice. May contain any additional information. If provided, the default header and footer are not used (Optional) |
| Client
Depending on the presence of certain fields, the search for a client occurs in the following order: An existing client is searched by ID An existing client is searched by correlation ID An existing client is searched by registration number An existing client is searched by name and email (for legal entities by name only) If a client is not found, it will be created. If an external ID is provided, a mapping is created for subsequent search. If a client is found, then all provided data is updated. Client type will be set as Corporate if either is_company = true or client_vat_number is provided. |
|
| client_correlation_id | Client ID from external system (Optional) |
| client_id | Client ID in PayTraq (Optional) |
| client_name | Client name |
| client_email | Client e-mail (Optional) |
| client_phone | Client phone (Optional) |
| client_details | Additional information included in the client billing details (Optional) |
| client_reg_number | Client registration number (Optional) |
| client_vat_number | Client VAT number (Optional) |
| client_contract | Client contract/agreement number. Can be part of the invoice number (Optional) |
| client_project_name | Project name (Optional) |
| client_group_name | Client group name (Optional) |
| is_company | Boolean value (true or false) (Optional) |
| send_to | Boolean value (true or false) (Optional)
The invoice will be sent by email only if there is an e-mail address available for a client and the field send_to = true is passed |
| country_code | 2-letter ISO country code (Optional) |
| Items
The search for a service is carried out first by code (item_code), then by name (item_name), if a service is not found, then it will be created. By default the "Selling Services" operation type is used. Operation type which will be used in Billing API can be changed to "Other Income" upon request to customer support. |
|
| item_uom | Unit of measurement, if it is not found, then it will be created (Optional) |
| item_qty | Unit quantity |
| item_price | Unit price |
| item_discount | Discount as a percentage (Optional) |
| item_description | Line comment (Optional) |
| item_tax_rate | Tax rate as a percentage. If not specified, the default value is selected. If 0, then the tax key “No VAT” is selected. It is also possible to pass the name of the existed tax key (item_tax_name) instead of a tax rate (Optional) |
| item_account_code | GL account number, if not specified, the default value is selected (Optional) |
| item_period | Similar to period, but for a specific line item (Optional) |
| Payment
Payment data is optional, if it is provided then the invoice payment will be created |
|
| money_account_id | Unique system identifier for money account in Paytraq. See Get Bank Accounts and Get Cash Accounts requests from generic API. |
| date_paid | Date of payment. Format - YYYY-MM-DD |
|
If there are no errors in the request, the response code will be 200 OK. |
|
Response
{
"run_id": _run_id,
"status": "done",
"created_at": _created_at
}Webhook
{
"run_id": _run_id,
"status": _status,
"created_at": _created_at,
"completed_at": _completed_at
}| Tag | Description |
|---|---|
| run_id | Billing process ID |
| status | Process status:
|
Minimum set of fields for request
{
"billing": {
"invoices": [
{
"client": {
"client_name": _client_name
},
"items": [
{
"item_name": _item_name,
"item_qty": _item_qty,
"item_price": _item_price,
}
]
}
]
}
}
GETChecking Billing Process Status and Getting Generation Results
Request
GET api/billing/{run_id}| Tag | Description |
|---|---|
| run_id | Billing process ID |
Response
If the billing process is not yet completed:
{
"run_id": _run_id,
"status": _status,
"created_at": _created_at
}
If the billing process is completed:
{
"run_id": _run_id,
"status": _status,
"created_at": _created_at,
"completed_at": _completed_at,
"period_from": _period_from,
"period_till": _period_till,
"invoices": [
{
"client_correlation_id": _client_correlation_id,
"invoice_correlation_id": _invoice_correlation_id,
"client_id": _client_id,
"invoice_id": _doc_id,
"invoice_ref": _doc_ref,
"invoice_date": _doc_date,
"due_date": _due_date,
"total": _total,
"due": _due,
"currency": _currency,
"status": _status,
"is_sent": _is_sent,
"pdf_link": _pdf_link,
"invoice_link": _invoice_link,
"created_at": _created_at,
"updated_at": _updated_at
}
]
}| Tag | Description |
|---|---|
| invoice_id | Invoice ID in Paytraq |
| invoice_ref | Invoice Number in PayTraq |
| invoice_date | Invoice Date |
| due_date | Invoice Due Date |
| total | Invoice Total Amount |
| due | Invoice Due Amount |
| status | Invoice Status “draft” - Draft ”wait_approve” - Waiting for Approval ”wait_payment” - Waiting for Payment ”part_paid” - Partially Paid ”paid” - Paid ”voided” - Voided/Canceled |
| pdf_link | URL to get PDF invoice |
| invoice_link | Invoice Online Link |
| is_sent | Status of delivery (true/false) |
You cannot start a new billing process for the same company until the previous one is completed. In this case, the POST /api/billing/run request will return error 429 Too Many Requests
Examples
Starting of billing process request example
{
"billing": {
"period_id": "2",
"invoice_date": "2021-04-01",
"webhook_url": "https://webhook.site/7e73bced-da2b-4ad3-9910-3c9efd956d77",
"invoices": [
{
"client": {
"client_correlation_id": "1",
"client_name": "Milana Rush",
"client_email": "bugs@paytraq.com"
},
"invoice_correlation_id": "1",
"items": [
{
"item_name": "Management services",
"item_qty": "1",
"item_uom": "pcs.",
"item_price": "5.23"
},
{
"item_name": "Management fee",
"item_qty": "1",
"item_uom": "pcs.",
"item_price": "10.80"
},
{
"item_name": "Street lighting D2",
"item_qty": "1",
"item_uom": "pcs.",
"item_price": "2.28"
},
{
"item_name": "Savings fund",
"item_qty": "1",
"item_uom": "pcs.",
"item_tax_rate": "0",
"item_price": "9.25"
},
{
"item_name": "Cold water and sewage",
"item_qty": "15",
"item_uom": "m3",
"item_price": "1.50"
},
{
"item_name": "Road maintenance fund",
"item_qty": "1",
"item_uom": "pcs.",
"item_tax_rate": "0",
"item_price": "5"
}
]
},
{
"client": {
"client_name": "Mateo Leverenz"
},
"items": [
{
"item_name": "Management services",
"item_qty": "1",
"item_uom": "pcs.",
"item_price": "5.23"
},
{
"item_name": "Management fee",
"item_qty": "1",
"item_uom": "pcs.",
"item_price": "10.80"
},
{
"item_name": "Savings fund",
"item_qty": "1",
"item_uom": "pcs.",
"item_tax_rate": "0",
"item_price": "9.25"
},
{
"item_name": "Cold water and sewage",
"item_qty": "10",
"item_uom": "m3",
"item_price": "1.50"
},
{
"item_name": "Other services",
"item_qty": "1",
"item_price": "2.50"
}
]
}
]
}
}Getting generation results response example
{
"run_id": "1318",
"status": "done",
"created_at": "2021-04-07 22:27:46",
"completed_at": "2021-04-07 22:27:57",
"period_from": "2021-03-01",
"period_till": "2021-03-31",
"invoices": [
{
"due": "55.06",
"invoice_link": "https://go.paytraq.com/eInvoices/***",
"invoice_ref": "0421/00001",
"pdf_link": "https://go.paytraq.com/eInvoices/invoiceData/***",
"updated": "2021-04-07 22:27:52",
"status": "wait_payment",
"is_sent": true,
"invoice_date": "2021-04-07",
"created": "2021-04-07 22:27:52",
"total": "55.06",
"client_id": "7969",
"due_date": "2021-05-07",
"currency": "EUR",
"invoice_correlation_id": "1",
"invoice_id": "6272",
"client_correlation_id": "1"
},
{
"due": "42.78",
"invoice_link": "https://go.paytraq.com/eInvoices/***",
"invoice_ref": "0421/00002",
"pdf_link": "https://go.paytraq.com/eInvoices/invoiceData/***",
"updated": "2021-04-07 22:27:57",
"status": "wait_payment",
"is_sent": false,
"invoice_date": "2021-04-07",
"created": "2021-04-07 22:27:57",
"total": "42.78",
"client_id": "7970",
"due_date": "2021-05-07",
"currency": "EUR",
"invoice_correlation_id": "",
"invoice_id": "6273",
"client_correlation_id": ""
}
]
}