Download OpenAPI specification:Download
The January API is a set of programmatic endpoints that can be used to interact with January data. This API is documented in OpenAPI format.
January will generate an API token to use with all of your requests. You can attach the token in the header with the following key value:
Authorization: Bearer <API_TOKEN >
All API requests have a rate limit of 100 / minute. Please contact us if this is insufficient for your needs.
Endpoints that use pagination will accept page
and limit
arguments as query parameters.
A max of 1000 results per page will be returned. page
will default to 1 unless a value is given and limit
will default to 1000.
When reading paginated responses from the API, the follow response headers will be sent:
X-Page
: The current page
X-Per-Page
: The current limit
X-Total-Count
: The total number of pages availableAll currency fields should be provided as integers representing the number of cents.
In other words, the dollar amount $1.99 should be sent as 199
, not as 1.99
or as "$1.99"
.
Every response will contain a X-January-API-Request-ID value, unique to a response.
Success response structure
Successful responses are indicated with a 200-series HTTP code and a JSON-based payload. The data field in JSON responses will contain the specific objects associated with the leveraged resource.
Error response structure
Error responses are indicated with a non-200-series HTTP code and sometimes a JSON-based payload. We cannot guarantee that all error responses will contain the same response format or a consistent repsonse format, we recommend that the HTTP code's core meaning to take precedence.
In general, January will only make backwards-compatible changes to our APIs. For example, we might:
null
for a property even if we never returned null
for that property before as long as we documented the field as nullable)If we need to make a breaking change, we will introduce a new API endpoint. For example, the following would be breaking changes:
There are exceptions to this stability promise. Specifically, new APIs will be marked "Beta" for a while, and are not subject to this policy. This is to allow us to quickly iterate on APIs so they can better serve clients' needs. Clients making use of APIs marked "Beta" should expect to work directly with us to adjust to changes we make to the API as it evolves.
We will announce API deprecations in advance and provide a timeline for transitioning to replacements.
Webhooks allow you to opt into receiving real-time events about the accounts you've placed with January. These events are sent via HTTPS to your backend system. Some examples of real-time events include being alerted when a borrower has made a payment, or when an account has been fully paid off.
Note: Webhook events are only available for pre-chargeoff accounts.
To validate that a webhook was sent by January, every incoming request is signed with a signature stored under the HTTP Header x-signature
.
To extract the signature, please hash the request body using HMAC SHA-256, with your webhook key as the shared secret (see "Retrieving Your Webhook Key" below).
The signature you generate above should be equivalent to the signature we pass through the HTTP Header x-signature
. If not, the request may be from another source.
api@january.com
to rotate your key.To subscribe to a webhook, please contact api@january.com outlining:
payment_plan_created
). See "Webhook Events" section below for a list of webhooks.https://www.client-name.com/events/payment-plan/create
).POST
requests to this endpoint. To see a detailed request body schema, refer to the Webhooks documentation section below.The below is a list of all the webhook events you can subscribe to, followed by a description of what information will be shared:
placed
to resolved
.This below snippet is an example handler for webhook events (in Python).
def _is_valid_january_signature():
def wrapper(event_handler):
def wrapped_event_handler(*args):
webhook_signature = request.headers["x-signature"]
body = request.get_data()
secret_key = <your webhook key (ideally retrieved from some kind of secure secret storage)>
derived_signature = hmac.new(
bytes(
secret_key,
"utf-8",
),
body,
hashlib.sha256,
).hexdigest()
if hmac.compare_digest(
bytes(derived_signature, "utf-8"), bytes(webhook_signature, "utf-8")
):
return event_handler(*args)
else:
abort(403, "Invalid Signature")
wrapped_event_handler.__name__ = event_handler.__name__
return wrapped_event_handler
return wrapper
@api.route("/january_events/transactions", methods=("POST",))
@_is_valid_january_signature()
def handle_webhook():
logger.info(
"Webhook received",
{"json": request.json, "headers": request.headers},
)
return jsonify({"foo": "bar"}), 200
For support and feedback please email api@january.com, we'd love to hear from you.
(Stability: beta)
page | integer Page of results |
limit | integer Maximum number of results returned |
[- {
- "debt": {
- "debtID": "string",
- "status": "uploaded",
- "uploadedAt": "2019-08-24",
- "currentBalance": 0,
- "plans": [
- {
- "cadence": 0,
- "coveredAmount": 0,
- "installmentAmount": 0,
- "paymentMethodType": "string"
}
]
}
}
]
Update a debt or multiple debt balances (Stability: beta)
debtID required | string Client specific identifier for a debt. This is most likely an account number. |
required | Array of objects |
[- {
- "debtID": "string",
- "balanceAdjustments": [
- {
- "id": "string",
- "amount": 0,
- "type": "credit",
- "notes": "string"
}
]
}
]
{- "errors": [
- {
- "debtID": "string",
- "problem": "string",
- "balanceAdjustmentID": "string"
}
]
}
(Stability: beta)
debtID required | string Client specific identifier for a debt |
{- "debt": {
- "debtID": "string",
- "status": "uploaded",
- "uploadedAt": "2019-08-24",
- "currentBalance": 0,
- "plans": [
- {
- "cadence": 0,
- "coveredAmount": 0,
- "installmentAmount": 0,
- "paymentMethodType": "string"
}
]
}
}
(Stability: beta)
startDate | date |
endDate | date |
debtID | string Client specific identifier for a debt |
transactionType | string Enum: "adjustment" "payment" |
page | integer Page of results |
limit | integer Maximum number of results returned |
[- {
- "debtID": "string",
- "transactionUuid": "string",
- "clientTransactionID": "string",
- "transactionDate": "2019-08-24",
- "type": "string",
- "clientBorrowerID": "string",
- "status": "PENDING",
- "amount": 0,
- "paymentMethodType": "string"
}
]
Asynchronously create up to 10,000 new debts at a time. (Stability: beta)
required | object ($defs-debt) |
required | object (debtor) |
object (debtor) |
[ ]
{- "placementID": "string",
- "status": "pending"
}
Retrieve status of placement initiated by post /v2/placements. (Stability: beta)
placementID required | string |
{- "placementID": "string",
- "status": "pending",
- "totals": {
- "balance": 0,
- "records": 0
}, - "successes": [
- {
- "debtID": "string"
}
], - "failures": [
- {
- "debtID": "string",
- "reason": "string",
- "type": "duplicate-debt"
}
]
}
(Stability: production)
debtID required | string Client specific identifier for a debt. This is most likely an account number. |
type required | string Enum: "compliance" "swap" Type of recall request |
reason required | string Enum: "bankrupt" "deceased" "litigious-consumer" "active-military" "incarcerated" "other" Reason for recall request |
note | string Further detail on the recall request |
[- {
- "debtID": "string",
- "type": "compliance",
- "reason": "bankrupt",
- "note": "string"
}
]
{- "successes": [
- {
- "debtID": "string"
}
], - "failures": [
- {
- "debtID": "string",
- "reason": "string"
}
]
}
Receieve a real-time request when January, as the client, sends an email to a borrower
debtID | string Client specific identifier for a debt |
eventTime | string <date-time> When the event took place |
eventType | string Value: "emailSent" |
commID | string <uuid> January identifier for this communication |
emailAddress | string <email> The email address January sent an email to |
subject | string The subject line of the email |
{- "debtID": "string",
- "eventTime": "2023-03-22T19:39:47.954736+00:00",
- "eventType": "emailSent",
- "commID": "5636959f-19a1-4e26-87c4-27ee0779678b",
- "emailAddress": "user@example.com",
- "subject": "string"
}
Receieve a real-time request when January, as the client, receives an email from a borrower
debtID | string Client specific identifier for a debt |
eventTime | string <date-time> When the event took place |
eventType | string Value: "emailReceived" |
commID | string <uuid> January identifier for this communication |
emailAddress | string <email> The email address January received an email from |
subject | string The subject line of the email |
{- "debtID": "string",
- "eventTime": "2023-03-22T19:39:47.954736+00:00",
- "eventType": "emailReceived",
- "commID": "5636959f-19a1-4e26-87c4-27ee0779678b",
- "emailAddress": "user@example.com",
- "subject": "string"
}
Receieve a real-time request when January, as the client, makes an outbound phone call to a borrower at their request
debtID | string Client specific identifier for a debt |
eventTime | string <date-time> When the event took place |
eventType | string Value: "outboundPhone" |
commID | string <uuid> January identifier for this communication |
phoneNumber | string <phone> |
{- "debtID": "string",
- "eventTime": "2023-03-22T19:39:47.954736+00:00",
- "eventType": "outboundPhone",
- "commID": "5636959f-19a1-4e26-87c4-27ee0779678b",
- "phoneNumber": "string"
}
Receieve a real-time request when January, as the client, receives a phone call from a borrower
debtID | string Client specific identifier for a debt |
eventTime | string <date-time> When the event took place |
eventType | string Value: "inboundPhone" |
commID | string <uuid> January identifier for this communication |
phoneNumber | string <phone> |
{- "debtID": "string",
- "eventTime": "2023-03-22T19:39:47.954736+00:00",
- "eventType": "inboundPhone",
- "commID": "5636959f-19a1-4e26-87c4-27ee0779678b",
- "phoneNumber": "string"
}
Receieve a real-time request when a payment plan was created for an account.
Note: January prevents the creation of a payment plan within 7 days of an account's charge-off date. Borrowers are still able to make payments in full towards their overdue balance.
debtID | string Client specific identifier for a debt |
eventTime | string <date-time> When the event took place |
eventType | string Value: "paymentPlanCreated" |
planID | string <uuid> January identifier for the payment plan |
cadence | string Enum: "weekly" "every-two-weeks" "monthly" "first-and-fifteenth" Cadence at which this payment plan charges a borrower |
installmentAmount | integer Installment amount (in cents) to be charged at the cadence the borrower specifies |
coveredAmount | integer Total balance (in cents) to be covered under this payment plan |
firstPaymentDate | string <date> The day the payment plan starts and when we first charge a borrower |
{- "debtID": "string",
- "eventTime": "2023-03-22T19:39:47.954736+00:00",
- "eventType": "paymentPlanCreated",
- "planID": "b3e38790-d1c0-4afb-b75c-aa44e99a6877",
- "cadence": "every-two-weeks",
- "installmentAmount": 15050,
- "coveredAmount": 45150,
- "firstPaymentDate": "2023-03-30"
}
Receieve a real-time request when a payment plan was updated
debtID | string Client specific identifier for a debt |
eventTime | string <date-time> When the event took place |
eventType | string Value: "paymentPlanUpdated" |
planID | string <uuid> January identifier for the payment plan |
cadence | string Enum: "weekly" "every-two-weeks" "monthly" "first-and-fifteenth" Cadence at which this payment plan charges a borrower |
installmentAmount | integer Installment amount (in cents) to be charged at the cadence the borrower specifies |
coveredAmount | integer Total balance (in cents) to be covered under this payment plan |
firstPaymentDate | string <date> The day the payment plan starts and when we first charge a borrower |
{- "debtID": "string",
- "eventTime": "2023-03-22T19:39:47.954736+00:00",
- "eventType": "paymentPlanUpdated",
- "planID": "b3e38790-d1c0-4afb-b75c-aa44e99a6877",
- "cadence": "weekly",
- "installmentAmount": 30100,
- "coveredAmount": 45150,
- "firstPaymentDate": "2023-03-30"
}
Receieve a real-time request when a payment plan was deleted
debtID | string Client specific identifier for a debt |
eventTime | string <date-time> When the event took place |
eventType | string Value: "paymentPlanDeleted" |
planID | string <uuid> January identifier for the payment plan |
{- "debtID": "string",
- "eventTime": "2023-03-22T19:39:47.954736+00:00",
- "eventType": "paymentPlanDeleted",
- "planID": "b3e38790-d1c0-4afb-b75c-aa44e99a6877"
}
Receieve a real-time request when a payment is successfully received and applied to an account
debtID | string Client identifier for the debt this event pertains to |
eventTime | string <date-time> When the event took place |
eventType | string Value: "paymentReceived" |
paymentID | string <uuid> January identifier for the payment |
amount | integer Payment amount in cents |
paymentMethod | string Enum: "ach" "check" "debit" "plaid" |
{- "debtID": "string",
- "eventTime": "2023-03-22T19:39:47.954736+00:00",
- "eventType": "paymentReceived",
- "paymentID": "471b4c61-4e6a-414a-9a08-2528498de3f3",
- "amount": 25050,
- "paymentMethod": "ach"
}
Receieve a real-time request when a payment is returned (i.e. refunded or charged back)
debtID | string Client specific identifier for a debt |
eventTime | string <date-time> When the event took place |
eventType | string Value: "paymentReturned" |
returnedPaymentID | string <uuid> References the paymentID of the payment that was returned |
amount | integer <= 0 A negative integer amount returned in cents |
reason | string Enum: "chargeback" "refund" Describes whether the transaction was charged back or refunded |
{- "debtID": "string",
- "eventTime": "2023-03-22T19:39:47.954736+00:00",
- "eventType": "paymentReturned",
- "returnedPaymentID": "cec96196-7439-4643-9a38-b43dc8b35244",
- "amount": -25050,
- "reason": "chargeback"
}
Monitor the status of accounts. Possible statuses include:
placed
: January is working to collect on this account.ceased
: January is no longer working to collect on this account. Possible reasons include:canceled
: January is no longer working to collect on this account because it was recalled by the client.resolved
: January is no longer working to collect on this account because it has been paid in full.charged-off
: January is no longer working to collect on this account because it is charged-off.Receieve a real-time request when the status of an account changes
debtID | string Client specific identifier for a debt. This is most likely an account number. |
eventTime | string <date-time> When the event took place |
eventType | string Value: "accountStatusUpdate" |
previousStatus | string Enum: "placed" "resolved" "ceased" "canceled" "charged-off" |
currentStatus | string Enum: "placed" "resolved" "ceased" "canceled" "charged-off" |
{- "debtID": "string",
- "eventTime": "2023-03-22T19:39:47.954736+00:00",
- "eventType": "accountStatusUpdate",
- "previousStatus": "placed",
- "currentStatus": "placed"
}