Add manual position to potential invoice
What does this do? Adds a custom manual position (line item) to a potential invoice. Manual positions allow you to bill for external costs, flat fees, or other items that aren’t automatically created by tickets, products, or subscriptions.
When to use:
- To add external costs (e.g., translation services, license costs)
- To add travel expenses or other one-time charges
- To add flat rates with no ticket reference
- To add items that were missing from the original offer
How it works:
- Creates a new manual position entry stored in the potential invoice metadata
- The position appears immediately in the invoice preview
- Manual positions are fully integrated into tax and total calculations
- Only custom manual positions (type: manual) can be added, updated, or deleted
- Project manual positions (from project snapshots) are read-only and cannot be modified
Position requirements:
- Must provide a unique UUID for the position ID
- Title and price are required
- Price must be a positive number (net amount before tax)
Invoice ID Format: The invoice ID follows the format: {type}::{projectId}::{dateFrom}::{dateTo}
- Example: SingleProject::0e9d033a-ab41-4212-8637-66c4e3b01fe2::2025-10-01::2025-10-31
Permission requirements: Requires Invoices.manage permission and access to the project.
POST
/billing/potential-invoices/{id}/manual-positionsAuthorization
AuthorizationOAuth2 access token · headerrequiredScopes:
api:writeor
AuthorizationBearer token (JWT) · headerrequiredPath parameters
idstringrequiredPotential invoice ID in format: {type}::{projectId}::{dateFrom}::{dateTo}
Request body
requiredapplication/jsonidstring<uuid>requiredUnique identifier (UUID) for the manual position. This ID is used to reference the position in update and delete operations.
pricenumberrequiredNet price (before tax) for this manual position in the workspace currency
titlestringrequiredTitle or description of the manual position (e.g., "Workshop travel expenses", "Translation services")
Responses
200Manual position added successfully
successbooleanrequiredOperation success flag
401Unauthorized - Invalid or missing authentication token
403User lacks Invoices.manage permission or project access
404Potential invoice not found
Request
curl -X POST "https://leadtime.app/api/public/billing/potential-invoices/SingleProject%3A%3A0e9d033a-ab41-4212-8637-66c4e3b01fe2%3A%3A2025-10-01%3A%3A2025-10-31/manual-positions" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"id": "550e8400-e29b-41d4-a716-446655440000",
"price": 150,
"title": "Workshop travel expenses"
}'const response = await fetch("https://leadtime.app/api/public/billing/potential-invoices/SingleProject%3A%3A0e9d033a-ab41-4212-8637-66c4e3b01fe2%3A%3A2025-10-01%3A%3A2025-10-31/manual-positions", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({
"id": "550e8400-e29b-41d4-a716-446655440000",
"price": 150,
"title": "Workshop travel expenses"
})
});import requests
response = requests.post(
"https://leadtime.app/api/public/billing/potential-invoices/SingleProject%3A%3A0e9d033a-ab41-4212-8637-66c4e3b01fe2%3A%3A2025-10-01%3A%3A2025-10-31/manual-positions",
headers={
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
},
json={
"id": "550e8400-e29b-41d4-a716-446655440000",
"price": 150,
"title": "Workshop travel expenses"
},
)Response
{
"success": true
}Unauthorized - Invalid or missing authentication token
User lacks Invoices.manage permission or project access
Potential invoice not found