Skip to main content
Skip to Content

Agreements API

Agreements represent recurring retainer contracts with clients. They define monthly hour allowances, rates, and billing terms. Each agreement has periods (typically monthly) that track usage and rollover.

The Agreement Object

{
  "id": "agr_cuid123456",
  "client_id": "cli_xxxxx",
  "type_id": "agrtype_xxxxx",
  "title": "Monthly Support Retainer",
  "status": "active",
  "billing": {
    "monthly_fee": 5000.00,
    "hours_included": 40,
    "overage_rate": 150.00,
    "billing_day": 1
  },
  "rollover": {
    "enabled": true,
    "max_hours": 20,
    "expires_months": 3
  },
  "dates": {
    "start_date": "2026-01-01",
    "end_date": null,
    "next_renewal": "2027-01-01"
  },
  "contact_id": "con_xxxxx",
  "auto_invoice": true,
  "invoice_method": "create_draft",
  "current_period": {
    "id": "per_xxxxx",
    "start_date": "2026-01-01",
    "end_date": "2026-01-31",
    "hours_included": 40,
    "hours_used": 28.5,
    "hours_remaining": 11.5,
    "rollover_hours": 0
  },
  "notes": "Premium support package with 24/7 coverage",
  "created_at": "2025-12-15T10:00:00Z",
  "updated_at": "2026-01-20T14:30:00Z"
}

Agreement Fields

FieldTypeDescription
idstringUnique identifier (prefix: agr_)
client_idstringRequired. Associated client
type_idstringAgreement type category
titlestringRequired. Agreement name
statusenumAgreement status
billingobjectBilling configuration
rolloverobjectRollover settings
datesobjectContract dates
contact_idstringPrimary contact
auto_invoicebooleanGenerate invoices automatically
invoice_methodenumcreate_draft or auto_send
current_periodobjectCurrent period details
notesstringInternal notes
created_atdatetimeWhen created
updated_atdatetimeWhen last updated

Agreement Status

StatusDescription
draftNot yet active
activeCurrently in effect
pausedTemporarily suspended
expiredPast end date
cancelledTerminated early

Billing Object

FieldTypeDescription
monthly_feedecimalMonthly retainer fee
hours_includeddecimalHours included per month
overage_ratedecimalRate for hours beyond allowance
billing_dayintegerDay of month to generate invoice (1-28)

Rollover Object

FieldTypeDescription
enabledbooleanAllow unused hours to roll over
max_hoursdecimalMaximum rollover hours (cap)
expires_monthsintegerMonths until rollover expires

List Agreements

GET/v1/agreementsList all agreements

Returns a paginated list of agreements.

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number
per_pageinteger20Results per page (max: 100)
client_idstringFilter by client
statusstringFilter by status
type_idstringFilter by agreement type
expiring_soonbooleanAgreements expiring within 30 days
sortstringcreated_atSort by: created_at, start_date, monthly_fee
orderstringdescSort order: asc, desc

Request

curl "https://api.govantage.co/v1/agreements?status=active&client_id=cli_xxxxx" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx"

Response

{
  "data": [
    {
      "id": "agr_cuid123456",
      "client_id": "cli_xxxxx",
      "client_name": "Acme Corporation",
      "title": "Monthly Support Retainer",
      "status": "active",
      "billing": {
        "monthly_fee": 5000.00,
        "hours_included": 40
      },
      "current_period": {
        "hours_used": 28.5,
        "hours_remaining": 11.5,
        "percent_used": 71.25
      },
      "dates": {
        "start_date": "2026-01-01"
      }
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total": 45,
    "total_pages": 3
  },
  "summary": {
    "total_mrr": 125000.00,
    "active_agreements": 42,
    "expiring_soon": 3
  }
}

Create an Agreement

POST/v1/agreementsCreate a new agreement

Request Body

FieldTypeRequiredDescription
client_idstringYesClient ID
titlestringYesAgreement name
type_idstringNoAgreement type ID
start_datedateYesContract start date
end_datedateNoContract end date (null = ongoing)
monthly_feedecimalYesMonthly fee
hours_includeddecimalYesHours included per month
overage_ratedecimalNoOverage hourly rate
billing_dayintegerNoDay of month for invoicing (default: 1)
rollover_enabledbooleanNoEnable hour rollover
rollover_max_hoursdecimalNoMaximum rollover cap
rollover_expires_monthsintegerNoMonths until rollover expires
contact_idstringNoPrimary contact
auto_invoicebooleanNoAuto-generate invoices
invoice_methodstringNocreate_draft or auto_send
notesstringNoInternal notes

Request

curl -X POST "https://api.govantage.co/v1/agreements" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "cli_xxxxx",
    "title": "Monthly Support Retainer",
    "start_date": "2026-02-01",
    "monthly_fee": 5000,
    "hours_included": 40,
    "overage_rate": 150,
    "rollover_enabled": true,
    "rollover_max_hours": 20,
    "auto_invoice": true,
    "invoice_method": "create_draft"
  }'

Response

{
  "data": {
    "id": "agr_cuid789012",
    "client_id": "cli_xxxxx",
    "title": "Monthly Support Retainer",
    "status": "active",
    "billing": {
      "monthly_fee": 5000.00,
      "hours_included": 40,
      "overage_rate": 150.00,
      "billing_day": 1
    },
    "rollover": {
      "enabled": true,
      "max_hours": 20,
      "expires_months": null
    },
    "dates": {
      "start_date": "2026-02-01",
      "end_date": null
    },
    "current_period": {
      "id": "per_xxxxx",
      "start_date": "2026-02-01",
      "end_date": "2026-02-28",
      "hours_included": 40,
      "hours_used": 0,
      "hours_remaining": 40
    },
    "created_at": "2026-01-25T10:30:00Z"
  }
}

When an agreement is created, the first period is automatically generated based on the start date.


Get an Agreement

GET/v1/agreements/:idRetrieve an agreement by ID

Query Parameters

ParameterTypeDescription
includestringComma-separated: client, periods, time_entries, invoices

Request

curl "https://api.govantage.co/v1/agreements/agr_cuid123456?include=periods" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx"

Update an Agreement

PUT/v1/agreements/:idUpdate an agreement

Changes to monthly_fee, hours_included, or overage_rate take effect from the next period. Current period values are preserved.

Request

curl -X PUT "https://api.govantage.co/v1/agreements/agr_cuid123456" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "monthly_fee": 6000,
    "hours_included": 50,
    "notes": "Upgraded package starting February"
  }'

Cancel an Agreement

POST/v1/agreements/:id/cancelCancel an agreement
curl -X POST "https://api.govantage.co/v1/agreements/agr_cuid123456/cancel" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "effective_date": "2026-01-31",
    "reason": "Client ended services"
  }'

Agreement Periods

Periods represent billing cycles within an agreement (typically monthly).

The Period Object

{
  "id": "per_cuid123456",
  "agreement_id": "agr_xxxxx",
  "start_date": "2026-01-01",
  "end_date": "2026-01-31",
  "status": "active",
  "hours": {
    "included": 40,
    "rollover_in": 5,
    "total_available": 45,
    "used": 28.5,
    "remaining": 16.5,
    "overage": 0
  },
  "billing": {
    "base_fee": 5000.00,
    "overage_amount": 0,
    "total": 5000.00
  },
  "invoice_id": null,
  "closed_at": null
}

List Periods

GET/v1/agreements/:id/periodsList agreement periods
curl "https://api.govantage.co/v1/agreements/agr_cuid123456/periods?limit=12" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx"

Response

{
  "data": [
    {
      "id": "per_jan2026",
      "start_date": "2026-01-01",
      "end_date": "2026-01-31",
      "status": "active",
      "hours": {
        "total_available": 45,
        "used": 28.5,
        "remaining": 16.5
      }
    },
    {
      "id": "per_dec2025",
      "start_date": "2025-12-01",
      "end_date": "2025-12-31",
      "status": "closed",
      "hours": {
        "total_available": 40,
        "used": 35,
        "remaining": 0,
        "rolled_over": 5
      },
      "invoice_id": "inv_xxxxx"
    }
  ]
}

Get Period Details

GET/v1/agreements/:id/periods/:periodIdGet period details
curl "https://api.govantage.co/v1/agreements/agr_cuid123456/periods/per_jan2026?include=time_entries" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx"

Close Period Manually

POST/v1/agreements/:id/periods/:periodId/closeClose a period early

Periods are normally closed automatically by a daily cron job. Use this to close early.

curl -X POST "https://api.govantage.co/v1/agreements/agr_cuid123456/periods/per_jan2026/close" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "generate_invoice": true
  }'

Retainer Usage

Log Time Against Retainer

Time entries can be logged directly against an agreement:

curl -X POST "https://api.govantage.co/v1/time-entries" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "usr_xxxxx",
    "date": "2026-01-25",
    "hours": 2.5,
    "description": "Monthly maintenance tasks",
    "agreement_id": "agr_cuid123456",
    "client_id": "cli_xxxxx"
  }'

When you log time against an agreement, it automatically draws from the current period’s hour allowance. Overage is calculated when hours exceed the allowance.

Check Retainer Balance

GET/v1/agreements/:id/balanceGet current balance
curl "https://api.govantage.co/v1/agreements/agr_cuid123456/balance" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx"

Response

{
  "data": {
    "period": {
      "start_date": "2026-01-01",
      "end_date": "2026-01-31",
      "days_remaining": 6
    },
    "hours": {
      "included": 40,
      "rollover": 5,
      "total_available": 45,
      "used": 28.5,
      "remaining": 16.5,
      "overage": 0,
      "burn_rate_daily": 1.4
    },
    "projection": {
      "estimated_end_usage": 36.9,
      "estimated_remaining": 8.1,
      "will_have_overage": false
    },
    "value": {
      "monthly_fee": 5000.00,
      "hours_value": 4275.00,
      "remaining_value": 2475.00
    }
  }
}

Drawdown Report

GET/v1/agreements/drawdownRetainer drawdown summary

Get a summary of all active retainers and their current status.

curl "https://api.govantage.co/v1/agreements/drawdown" \
  -H "Authorization: Bearer vnt_sk_live_xxxxx"

Response

{
  "data": [
    {
      "agreement_id": "agr_xxxxx",
      "client_name": "Acme Corporation",
      "title": "Monthly Support Retainer",
      "period_end_date": "2026-01-31",
      "hours_available": 45,
      "hours_used": 28.5,
      "percent_used": 63.3,
      "status": "on_track"
    },
    {
      "agreement_id": "agr_yyyyy",
      "client_name": "Beta Industries",
      "title": "Development Retainer",
      "period_end_date": "2026-01-31",
      "hours_available": 80,
      "hours_used": 78,
      "percent_used": 97.5,
      "status": "near_limit"
    }
  ],
  "summary": {
    "total_mrr": 125000.00,
    "total_hours_available": 850,
    "total_hours_used": 625,
    "utilization_percent": 73.5
  }
}

Drawdown Status

StatusDescription
on_trackUsage is healthy
under_utilizedLess than 50% used with <25% time remaining
near_limit90%+ used
over_limitIn overage

Agreement Types

List Agreement Types

GET/v1/agreement-typesList agreement types
{
  "data": [
    { "id": "agrtype_support", "name": "Support Retainer", "default_hours": 40 },
    { "id": "agrtype_dev", "name": "Development Retainer", "default_hours": 80 },
    { "id": "agrtype_hosting", "name": "Hosting & Maintenance", "default_hours": 10 }
  ]
}

Webhooks

Subscribe to agreement events:

EventDescription
agreement.createdNew agreement created
agreement.updatedAgreement details changed
agreement.cancelledAgreement cancelled
agreement.period_closedPeriod closed
agreement.near_limit90% of hours used
agreement.over_limitHours exceeded allowance
agreement.expiring_soonAgreement expiring within 30 days

Next Steps