GRN Creation API
curl --request POST \
--url https://api.pazy.io/v1.0/procurement/grnimport requests
url = "https://api.pazy.io/v1.0/procurement/grn"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.pazy.io/v1.0/procurement/grn', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.pazy.io/v1.0/procurement/grn",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.pazy.io/v1.0/procurement/grn"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.pazy.io/v1.0/procurement/grn")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pazy.io/v1.0/procurement/grn")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyGRN APIs
GRN Creation API
Create Goods Receipt Notes (GRN) with line items linked to purchase orders
GRN Creation API
curl --request POST \
--url https://api.pazy.io/v1.0/procurement/grnimport requests
url = "https://api.pazy.io/v1.0/procurement/grn"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.pazy.io/v1.0/procurement/grn', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.pazy.io/v1.0/procurement/grn",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.pazy.io/v1.0/procurement/grn"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.pazy.io/v1.0/procurement/grn")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pazy.io/v1.0/procurement/grn")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyAuthentication
All requests require an API key in the request headers. Headers:Authorization: Api-Key YOUR_API_KEY
Content-Type: application/json
Request
Content-Type:application/json
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
grnNumber | string | Yes | GRN number to assign to the document (minimum 1 character) |
lineItems | array | Yes | List of line items that make up the GRN (minimum 1 item required) |
poId | string | Yes | Purchase order ID that this GRN is linked to (minimum 1 character) |
receivedDate | string | Yes | Received date for the GRN in ISO-8601 format (YYYY-MM-DD) |
remark | string | No | Remark for the GRN (minimum 1 character) |
referenceNo | string | No | Reference number for the GRN (minimum 1 character) |
description | string | No | Description for the GRN (minimum 1 character) |
tags | object | No | Custom fields configured for the organization. Each key is a field slug and each value is an object containing value. Supports dropdown, text, date, and numeric fields. |
Line Items Object
Each item in thelineItems array must contain the following fields:
| Parameter | Type | Required | Description |
|---|---|---|---|
quantity | number | Yes | Quantity received for the line item |
rate | number | Yes | Unit rate to be applied to the line item |
identifier | string | Yes | Description of the line item (minimum 1 character) |
tags | object | No | Line-level custom fields using organization-configured field slugs. Dropdown values are tag IDs; date values use YYYY-MM-DD; numeric values are numbers. |
Custom Fields
Custom fields are accepted on the GRN and on each line item using thetags object. The API resolves the field type from the organization configuration, so clients only need to send the configured slug and value.
To get the slugs and field types available to your organization, call the Tag List API and use each data.tags[].id value as the key in tags. For dropdown fields, use the Tag Detail API with that slug to retrieve valid option IDs.
{
"tags": {
"receipt-source": { "value": "Warehouse" },
"received-value": { "value": 125000.5 }
},
"lineItems": [
{
"identifier": "SKU-001",
"quantity": 100,
"rate": 50,
"tags": { "warehouse": { "value": "WH-01" } }
}
]
}
Code Examples
curl -X POST https://api.pazy.io/v1.0/procurement/grn \
-H "Authorization: Api-Key YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"grnNumber": "GRN-2024-001",
"poId": "po_identifier",
"receivedDate": "2024-02-15",
"description": "Goods receipt for office supplies",
"remark": "All items received in good condition",
"referenceNo": "REF-2024-001",
"lineItems": [
{
"identifier": "SKU-001",
"quantity": 100,
"rate": 50.00
},
{
"identifier": "SKU-002",
"quantity": 50,
"rate": 75.50
}
]
}'
const response = await fetch('https://api.pazy.io/v1.0/procurement/grn', {
method: 'POST',
headers: {
'Authorization': 'Api-Key YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
grnNumber: 'GRN-2024-001',
poId: 'po_identifier',
receivedDate: '2024-02-15',
description: 'Goods receipt for office supplies',
remark: 'All items received in good condition',
referenceNo: 'REF-2024-001',
lineItems: [
{
identifier: 'SKU-001',
quantity: 100,
rate: 50.00
},
{
identifier: 'SKU-002',
quantity: 50,
rate: 75.50
}
]
})
});
const result = await response.json();
import requests
url = "https://api.pazy.io/v1.0/procurement/grn"
headers = {
"Authorization": "Api-Key YOUR_API_KEY",
"Content-Type": "application/json"
}
payload = {
"grnNumber": "GRN-2024-001",
"poId": "po_identifier",
"receivedDate": "2024-02-15",
"description": "Goods receipt for office supplies",
"remark": "All items received in good condition",
"referenceNo": "REF-2024-001",
"lineItems": [
{
"identifier": "SKU-001",
"quantity": 100,
"rate": 50.00
},
{
"identifier": "SKU-002",
"quantity": 50,
"rate": 75.50
}
]
}
response = requests.post(url, headers=headers, json=payload)
result = response.json()
Success Response
HTTP Status:200 OK
Response Fields:
| Field | Type | Description |
|---|---|---|
ok | boolean | Indicates whether the request was successful |
data | object | Contains the GRN creation response data |
data.id | string | Unique identifier for the GRN |
data.grnNumber | string | GRN number assigned to the document |
data.status | string | Current status of the GRN |
Response Example
{
"ok": true,
"data": {
"id": "grn_identifier",
"grnNumber": "GRN-2024-001",
"status": "CREATED"
}
}
Error Responses
Missing Required Fields
HTTP Status:400 Bad Request
{
"ok": false,
"error": {
"code": "MISSING_REQUIRED_FIELD",
"message": "grnNumber is required"
}
}
400 Bad Request
{
"ok": false,
"error": {
"code": "PURCHASE_ORDER_ID_REQUIRED",
"message": "Purchase order ID required"
}
}
Invalid Date
HTTP Status:400 Bad Request
{
"ok": false,
"error": {
"code": "INVALID_DATE",
"message": "Invalid date"
}
}
Invalid Expected Delivery Date
HTTP Status:400 Bad Request
{
"ok": false,
"error": {
"code": "INVALID_EXPECTED_DELIVERY_DATE",
"message": "Invalid expected delivery date"
}
}
Invalid Line Items
HTTP Status:400 Bad Request
{
"ok": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed: /body/lineItems: must NOT have fewer than 1 items"
}
}
400 Bad Request
{
"ok": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed: /body/lineItems/0/quantity: must be number"
}
}
400 Bad Request
{
"ok": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed: /body/lineItems/0/identifier: must NOT have fewer than 1 characters"
}
}
Purchase Order Not Found
HTTP Status:404 Not Found
{
"ok": false,
"error": {
"code": "PURCHASE_ORDER_NOT_FOUND",
"message": "Purchase order not found"
}
}
GRN Not Found
HTTP Status:404 Not Found
{
"ok": false,
"error": {
"code": "GRN_NOT_FOUND",
"message": "GRN not found"
}
}
Invalid State
HTTP Status:400 Bad Request
{
"ok": false,
"error": {
"code": "INVALID_STATE",
"message": "Invalid state"
}
}
Invalid Matching Type
HTTP Status:400 Bad Request
{
"ok": false,
"error": {
"code": "INVALID_MATCHING_TYPE",
"message": "Invalid matching type"
}
}
Invalid Procurement Type
HTTP Status:400 Bad Request
{
"ok": false,
"error": {
"code": "INVALID_PROCUREMENT_TYPE",
"message": "Invalid procurement type"
}
}
Invalid Source
HTTP Status:400 Bad Request
{
"ok": false,
"error": {
"code": "INVALID_SOURCE",
"message": "Invalid source"
}
}
Invalid Type
HTTP Status:400 Bad Request
{
"ok": false,
"error": {
"code": "INVALID_TYPE",
"message": "Invalid type"
}
}
Invalid GSTIN
HTTP Status:400 Bad Request
{
"ok": false,
"error": {
"code": "INVALID_GSTIN",
"message": "Invalid GSTIN"
}
}
Invalid Currency
HTTP Status:400 Bad Request
{
"ok": false,
"error": {
"code": "INVALID_CURRENCY",
"message": "Invalid currency Only INR is supported at the moment"
}
}
Vendor Not Found
HTTP Status:404 Not Found
{
"ok": false,
"error": {
"code": "VENDOR_NOT_FOUND",
"message": "Vendor not found"
}
}
Authentication Errors
HTTP Status:401 Unauthorized
{
"ok": false,
"error": {
"code": "MISSING_CREDENTIALS",
"message": "Missing Credentials"
}
}
{
"ok": false,
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid API Key"
}
}
Permission Errors
HTTP Status:403 Forbidden
{
"ok": false,
"error": {
"code": "INSUFFICIENT_PERMISSIONS",
"message": "Permission check failed - PERMISSION_CHECK_FAILED"
}
}
GRN Creation Errors
HTTP Status:500 Internal Server Error
{
"ok": false,
"error": {
"code": "PROCUREMENT_CREATION_FAILED",
"message": "Error creating procurement"
}
}
Internal Error
HTTP Status:500 Internal Server Error
{
"ok": false,
"error": {
"code": "INTERNAL_ERROR",
"message": "Internal error"
}
}
Best Practices
GRN Creation
- Ensure all required fields (
grnNumber,lineItems,poId,receivedDate) are provided - Use ISO 8601 date format (YYYY-MM-DD) for the
receivedDatefield - Provide at least one line item with valid
quantity,rate, andidentifiervalues - The
poIdmust reference an existing purchase order in the system - Use
descriptionto provide context about the goods received - Include
remarkfor any special notes or conditions about the receipt - Use
referenceNoto link the GRN to external reference numbers or documents - Ensure the received date is not in the future and aligns with the purchase order timeline
Line Items
- Ensure each line item has a unique
identifierthat matches the purchase order line items - Use positive numbers for
quantityandrate - The quantity received should typically match or be less than the quantity ordered in the purchase order
- Verify that line items correspond to the linked purchase order
Was this page helpful?